int ui_wait_key() { if (boardEnableKeyRepeat.value) return ui_wait_key_with_repeat(); pthread_mutex_lock(&key_queue_mutex); int timeouts = UI_WAIT_KEY_TIMEOUT_SEC; #ifdef PHILZ_TOUCH_RECOVERY int display_state = 0; #endif // Time out after REFRESH_TIME_USB_INTERVAL seconds to catch volume changes, refresh clock, and loop for // UI_WAIT_KEY_TIMEOUT_SEC to restart a device not connected to USB do { struct timeval now; struct timespec timeout; gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec; timeout.tv_nsec = now.tv_usec * 1000; timeout.tv_sec += REFRESH_TIME_USB_INTERVAL; int rc = 0; while (key_queue_len == 0 && rc != ETIMEDOUT) { rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); if (volumes_changed()) { pthread_mutex_unlock(&key_queue_mutex); return REFRESH; } } timeouts -= REFRESH_TIME_USB_INTERVAL; #ifdef PHILZ_TOUCH_RECOVERY ui_refresh_display_state(&display_state); #endif } while ((timeouts > 0 || usb_connected()) && key_queue_len == 0); int key = -1; if (key_queue_len > 0) { key = key_queue[0]; memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); } pthread_mutex_unlock(&key_queue_mutex); return key; }
int ui_wait_key_with_repeat() { int key = -1; // Loop to wait for more keys. do { int timeouts = UI_WAIT_KEY_TIMEOUT_SEC; int rc = 0; struct timeval now; struct timespec timeout; pthread_mutex_lock(&key_queue_mutex); while (key_queue_len == 0 && timeouts > 0) { gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec; timeout.tv_nsec = now.tv_usec * 1000; timeout.tv_sec += REFRESH_TIME_USB_INTERVAL; rc = 0; while (key_queue_len == 0 && rc != ETIMEDOUT) { rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); if (volumes_changed()) { pthread_mutex_unlock(&key_queue_mutex); return REFRESH; } } timeouts -= REFRESH_TIME_USB_INTERVAL; } pthread_mutex_unlock(&key_queue_mutex); if (rc == ETIMEDOUT && !usb_connected()) { return -1; } // Loop to wait wait for more keys, or repeated keys to be ready. while (1) { unsigned long now_msec; gettimeofday(&now, NULL); now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000); pthread_mutex_lock(&key_queue_mutex); // Replacement for the while conditional, so we don't have to lock the entire // loop, because that prevents the input system from touching the variables while // the loop is running which causes problems. if (key_queue_len == 0) { pthread_mutex_unlock(&key_queue_mutex); break; } key = key_queue[0]; memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); // sanity check the returned key. if (key < 0) { pthread_mutex_unlock(&key_queue_mutex); return key; } // Check for already released keys and drop them if they've repeated. if (!key_pressed[key] && key_last_repeat[key] > 0) { pthread_mutex_unlock(&key_queue_mutex); continue; } if (key_can_repeat(key)) { // Re-add the key if a repeat is expected, since we just popped it. The // if below will determine when the key is actually repeated (returned) // in the mean time, the key will be passed through the queue over and // over and re-evaluated each time. if (key_pressed[key]) { key_queue[key_queue_len] = key; key_queue_len++; } if ((now_msec > key_press_time[key] + UI_KEY_WAIT_REPEAT && now_msec > key_last_repeat[key] + UI_KEY_REPEAT_INTERVAL) || key_last_repeat[key] == 0) { key_last_repeat[key] = now_msec; } else { // Not ready pthread_mutex_unlock(&key_queue_mutex); continue; } } pthread_mutex_unlock(&key_queue_mutex); return key; } } while (1); return key; }