Loading Android.mk +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ else RECOVERY_NAME := CWM-based Recovery endif RECOVERY_VERSION := $(RECOVERY_NAME) v6.0.1.1 RECOVERY_VERSION := $(RECOVERY_NAME) v6.0.1.2 LOCAL_CFLAGS += -DRECOVERY_VERSION="$(RECOVERY_VERSION)" RECOVERY_API_VERSION := 2 Loading common.h +3 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,9 @@ typedef struct { const char* fs_options; const char* fs_options2; const char* lun; // (/sdcard, /emmc, /external_sd only) LUN file to // use when mounting via USB mass storage } Volume; typedef struct { Loading extendedcommands.c +133 −23 Original line number Diff line number Diff line Loading @@ -433,25 +433,144 @@ void show_nandroid_delete_menu(const char* path) } } #ifndef BOARD_UMS_LUNFILE #define BOARD_UMS_LUNFILE "/sys/devices/platform/usb_mass_storage/lun0/file" #endif #define MAX_NUM_USB_VOLUMES 3 #define LUN_FILE_EXPANDS 2 void show_mount_usb_storage_menu() { struct lun_node { const char *lun_file; struct lun_node *next; }; static struct lun_node *lun_head = NULL; static struct lun_node *lun_tail = NULL; int control_usb_storage_set_lun(Volume* vol, bool enable, const char *lun_file) { char c = 0; const char *vol_device = enable ? vol->device : &c; int fd; Volume *vol = volume_for_path("/sdcard"); if ((fd = open(BOARD_UMS_LUNFILE, O_WRONLY)) < 0) { LOGE("Unable to open ums lunfile (%s)", strerror(errno)); struct lun_node *node; // Verify that we have not already used this LUN file for(node = lun_head; node; node = node->next) { if (!strcmp(node->lun_file, lun_file)) { // Skip any LUN files that are already in use return -1; } } // Open a handle to the LUN file LOGI("Trying %s on LUN file %s\n", vol->device, lun_file); if ((fd = open(lun_file, O_WRONLY)) < 0) { LOGW("Unable to open ums lunfile %s (%s)\n", lun_file, strerror(errno)); return -1; } if ((write(fd, vol->device, strlen(vol->device)) < 0) && (!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) { LOGE("Unable to write to ums lunfile (%s)", strerror(errno)); // Write the volume path to the LUN file if ((write(fd, vol_device, strlen(vol_device)) < 0) && (!enable || !vol->device2 || (write(fd, vol->device2, strlen(vol->device2)) < 0))) { LOGW("Unable to write to ums lunfile %s (%s)\n", lun_file, strerror(errno)); close(fd); return -1; } else { // Volume path to LUN association succeeded close(fd); // Save off a record of this lun_file being in use now node = (struct lun_node *)malloc(sizeof(struct lun_node)); node->lun_file = strdup(lun_file); node->next = NULL; if (lun_head == NULL) lun_head = lun_tail = node; else { lun_tail->next = node; lun_tail = node; } LOGI("Successfully %sshared %s on LUN file %s\n", enable ? "" : "un", vol->device, lun_file); return 0; } } int control_usb_storage_for_lun(Volume* vol, bool enable) { static const char* lun_files[] = { #ifdef BOARD_UMS_LUNFILE BOARD_UMS_LUNFILE, #endif "/sys/devices/platform/usb_mass_storage/lun%d/file", "/sys/class/android_usb/android0/f_mass_storage/lun/file", "/sys/class/android_usb/android0/f_mass_storage/lun_ex/file", NULL }; // If recovery.fstab specifies a LUN file, use it if (vol->lun) { return control_usb_storage_set_lun(vol, enable, vol->lun); } // Try to find a LUN for this volume // - iterate through the lun file paths // - expand any %d by LUN_FILE_EXPANDS int lun_num = 0; int i; for(i = 0; lun_files[i]; i++) { const char *lun_file = lun_files[i]; for(lun_num = 0; lun_num < LUN_FILE_EXPANDS; lun_num++) { char formatted_lun_file[255]; // Replace %d with the LUN number bzero(formatted_lun_file, 255); snprintf(formatted_lun_file, 254, lun_file, lun_num); // Attempt to use the LUN file if (control_usb_storage_set_lun(vol, enable, formatted_lun_file) == 0) { return 0; } } } // All LUNs were exhausted and none worked LOGW("Could not %sable %s on LUN %d\n", enable ? "en" : "dis", vol->device, lun_num); return -1; // -1 failure, 0 success } int control_usb_storage(Volume **volumes, bool enable) { int res = -1; int i; for(i = 0; i < MAX_NUM_USB_VOLUMES; i++) { Volume *volume = volumes[i]; if (volume) { int vol_res = control_usb_storage_for_lun(volume, enable); if (vol_res == 0) res = 0; // if any one path succeeds, we return success } } // Release memory used by the LUN file linked list struct lun_node *node = lun_head; while(node) { struct lun_node *next = node->next; free((void *)node->lun_file); free(node); node = next; } lun_head = lun_tail = NULL; return res; // -1 failure, 0 success } void show_mount_usb_storage_menu() { // Build a list of Volume objects; some or all may not be valid Volume* volumes[MAX_NUM_USB_VOLUMES] = { volume_for_path("/sdcard"), volume_for_path("/emmc"), volume_for_path("/external_sd") }; // Enable USB storage if (control_usb_storage(volumes, 1)) return; static char* headers[] = { "USB Mass Storage device", "Leaving this menu unmount", "your SD card from your PC.", Loading @@ -468,17 +587,8 @@ void show_mount_usb_storage_menu() break; } if ((fd = open(BOARD_UMS_LUNFILE, O_WRONLY)) < 0) { LOGE("Unable to open ums lunfile (%s)", strerror(errno)); return -1; } char ch = 0; if (write(fd, &ch, 1) < 0) { LOGE("Unable to write to ums lunfile (%s)", strerror(errno)); close(fd); return -1; } // Disable USB storage control_usb_storage(volumes, 0); } int confirm_selection(const char* title, const char* confirm) Loading roots.c +4 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ static int parse_options(char* options, Volume* volume) { volume->fs_options = strdup(option + 11); } else if (strncmp(option, "fs_options2=", 12) == 0) { volume->fs_options2 = strdup(option + 12); } else if (strncmp(option, "lun=", 4) == 0) { volume->lun = strdup(option + 4); } else { LOGE("bad option \"%s\"\n", option); return -1; Loading @@ -90,6 +92,7 @@ void load_volume_table() { device_volumes[0].fs_type2 = NULL; device_volumes[0].fs_options = NULL; device_volumes[0].fs_options2 = NULL; device_volumes[0].lun = NULL; device_volumes[0].length = 0; num_volumes = 1; Loading Loading @@ -139,6 +142,7 @@ void load_volume_table() { device_volumes[num_volumes].fs_type2 = NULL; device_volumes[num_volumes].fs_options = NULL; device_volumes[num_volumes].fs_options2 = NULL; device_volumes[num_volumes].lun = NULL; if (parse_options(options, device_volumes + num_volumes) != 0) { LOGE("skipping malformed recovery.fstab line: %s\n", original); Loading ui.c +57 −25 Original line number Diff line number Diff line Loading @@ -888,10 +888,24 @@ int ui_wait_key() return key; } // util for ui_wait_key_with_repeat int key_can_repeat(int key) { int k = 0; for (;k < boardNumRepeatableKeys; ++k) { if (boardRepeatableKeys[k] == key) { break; } } if (k < boardNumRepeatableKeys) return 1; return 0; } int ui_wait_key_with_repeat() { int key = -1; // Loop to wait for more keys. do { struct timeval now; struct timespec timeout; Loading @@ -901,53 +915,71 @@ int ui_wait_key_with_repeat() timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC; int rc = 0; while (key_queue_len == 0 && rc != ETIMEDOUT) { pthread_mutex_lock(&key_queue_mutex); while (key_queue_len == 0 && rc != ETIMEDOUT) { rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); } pthread_mutex_unlock(&key_queue_mutex); if (rc == ETIMEDOUT && !usb_connected()) { return -1; } if (rc == ETIMEDOUT && !usb_connected()) return -1; while (key_queue_len > 0) { // Loop to wait wait for more keys, or repeated keys to be ready. while (1) { unsigned long now_msec; usleep(1); gettimeofday(&now, NULL); now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000); key = key_queue[0]; pthread_mutex_lock(&key_queue_mutex); memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); pthread_mutex_unlock(&key_queue_mutex); if (!key_pressed[key]) { if (key_last_repeat[key] > 0) continue; else return key; // 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; } int k = 0; for (;k < boardNumRepeatableKeys; ++k) { if (boardRepeatableKeys[k] == key) { 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 (k < boardNumRepeatableKeys) { 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) || } 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 if (key_last_repeat[key] > 0) { } else { // Not ready pthread_mutex_unlock(&key_queue_mutex); continue; } } pthread_mutex_unlock(&key_queue_mutex); return key; } } while (key_queue_len == 0); } while (1); return key; } Loading Loading
Android.mk +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ else RECOVERY_NAME := CWM-based Recovery endif RECOVERY_VERSION := $(RECOVERY_NAME) v6.0.1.1 RECOVERY_VERSION := $(RECOVERY_NAME) v6.0.1.2 LOCAL_CFLAGS += -DRECOVERY_VERSION="$(RECOVERY_VERSION)" RECOVERY_API_VERSION := 2 Loading
common.h +3 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,9 @@ typedef struct { const char* fs_options; const char* fs_options2; const char* lun; // (/sdcard, /emmc, /external_sd only) LUN file to // use when mounting via USB mass storage } Volume; typedef struct { Loading
extendedcommands.c +133 −23 Original line number Diff line number Diff line Loading @@ -433,25 +433,144 @@ void show_nandroid_delete_menu(const char* path) } } #ifndef BOARD_UMS_LUNFILE #define BOARD_UMS_LUNFILE "/sys/devices/platform/usb_mass_storage/lun0/file" #endif #define MAX_NUM_USB_VOLUMES 3 #define LUN_FILE_EXPANDS 2 void show_mount_usb_storage_menu() { struct lun_node { const char *lun_file; struct lun_node *next; }; static struct lun_node *lun_head = NULL; static struct lun_node *lun_tail = NULL; int control_usb_storage_set_lun(Volume* vol, bool enable, const char *lun_file) { char c = 0; const char *vol_device = enable ? vol->device : &c; int fd; Volume *vol = volume_for_path("/sdcard"); if ((fd = open(BOARD_UMS_LUNFILE, O_WRONLY)) < 0) { LOGE("Unable to open ums lunfile (%s)", strerror(errno)); struct lun_node *node; // Verify that we have not already used this LUN file for(node = lun_head; node; node = node->next) { if (!strcmp(node->lun_file, lun_file)) { // Skip any LUN files that are already in use return -1; } } // Open a handle to the LUN file LOGI("Trying %s on LUN file %s\n", vol->device, lun_file); if ((fd = open(lun_file, O_WRONLY)) < 0) { LOGW("Unable to open ums lunfile %s (%s)\n", lun_file, strerror(errno)); return -1; } if ((write(fd, vol->device, strlen(vol->device)) < 0) && (!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) { LOGE("Unable to write to ums lunfile (%s)", strerror(errno)); // Write the volume path to the LUN file if ((write(fd, vol_device, strlen(vol_device)) < 0) && (!enable || !vol->device2 || (write(fd, vol->device2, strlen(vol->device2)) < 0))) { LOGW("Unable to write to ums lunfile %s (%s)\n", lun_file, strerror(errno)); close(fd); return -1; } else { // Volume path to LUN association succeeded close(fd); // Save off a record of this lun_file being in use now node = (struct lun_node *)malloc(sizeof(struct lun_node)); node->lun_file = strdup(lun_file); node->next = NULL; if (lun_head == NULL) lun_head = lun_tail = node; else { lun_tail->next = node; lun_tail = node; } LOGI("Successfully %sshared %s on LUN file %s\n", enable ? "" : "un", vol->device, lun_file); return 0; } } int control_usb_storage_for_lun(Volume* vol, bool enable) { static const char* lun_files[] = { #ifdef BOARD_UMS_LUNFILE BOARD_UMS_LUNFILE, #endif "/sys/devices/platform/usb_mass_storage/lun%d/file", "/sys/class/android_usb/android0/f_mass_storage/lun/file", "/sys/class/android_usb/android0/f_mass_storage/lun_ex/file", NULL }; // If recovery.fstab specifies a LUN file, use it if (vol->lun) { return control_usb_storage_set_lun(vol, enable, vol->lun); } // Try to find a LUN for this volume // - iterate through the lun file paths // - expand any %d by LUN_FILE_EXPANDS int lun_num = 0; int i; for(i = 0; lun_files[i]; i++) { const char *lun_file = lun_files[i]; for(lun_num = 0; lun_num < LUN_FILE_EXPANDS; lun_num++) { char formatted_lun_file[255]; // Replace %d with the LUN number bzero(formatted_lun_file, 255); snprintf(formatted_lun_file, 254, lun_file, lun_num); // Attempt to use the LUN file if (control_usb_storage_set_lun(vol, enable, formatted_lun_file) == 0) { return 0; } } } // All LUNs were exhausted and none worked LOGW("Could not %sable %s on LUN %d\n", enable ? "en" : "dis", vol->device, lun_num); return -1; // -1 failure, 0 success } int control_usb_storage(Volume **volumes, bool enable) { int res = -1; int i; for(i = 0; i < MAX_NUM_USB_VOLUMES; i++) { Volume *volume = volumes[i]; if (volume) { int vol_res = control_usb_storage_for_lun(volume, enable); if (vol_res == 0) res = 0; // if any one path succeeds, we return success } } // Release memory used by the LUN file linked list struct lun_node *node = lun_head; while(node) { struct lun_node *next = node->next; free((void *)node->lun_file); free(node); node = next; } lun_head = lun_tail = NULL; return res; // -1 failure, 0 success } void show_mount_usb_storage_menu() { // Build a list of Volume objects; some or all may not be valid Volume* volumes[MAX_NUM_USB_VOLUMES] = { volume_for_path("/sdcard"), volume_for_path("/emmc"), volume_for_path("/external_sd") }; // Enable USB storage if (control_usb_storage(volumes, 1)) return; static char* headers[] = { "USB Mass Storage device", "Leaving this menu unmount", "your SD card from your PC.", Loading @@ -468,17 +587,8 @@ void show_mount_usb_storage_menu() break; } if ((fd = open(BOARD_UMS_LUNFILE, O_WRONLY)) < 0) { LOGE("Unable to open ums lunfile (%s)", strerror(errno)); return -1; } char ch = 0; if (write(fd, &ch, 1) < 0) { LOGE("Unable to write to ums lunfile (%s)", strerror(errno)); close(fd); return -1; } // Disable USB storage control_usb_storage(volumes, 0); } int confirm_selection(const char* title, const char* confirm) Loading
roots.c +4 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ static int parse_options(char* options, Volume* volume) { volume->fs_options = strdup(option + 11); } else if (strncmp(option, "fs_options2=", 12) == 0) { volume->fs_options2 = strdup(option + 12); } else if (strncmp(option, "lun=", 4) == 0) { volume->lun = strdup(option + 4); } else { LOGE("bad option \"%s\"\n", option); return -1; Loading @@ -90,6 +92,7 @@ void load_volume_table() { device_volumes[0].fs_type2 = NULL; device_volumes[0].fs_options = NULL; device_volumes[0].fs_options2 = NULL; device_volumes[0].lun = NULL; device_volumes[0].length = 0; num_volumes = 1; Loading Loading @@ -139,6 +142,7 @@ void load_volume_table() { device_volumes[num_volumes].fs_type2 = NULL; device_volumes[num_volumes].fs_options = NULL; device_volumes[num_volumes].fs_options2 = NULL; device_volumes[num_volumes].lun = NULL; if (parse_options(options, device_volumes + num_volumes) != 0) { LOGE("skipping malformed recovery.fstab line: %s\n", original); Loading
ui.c +57 −25 Original line number Diff line number Diff line Loading @@ -888,10 +888,24 @@ int ui_wait_key() return key; } // util for ui_wait_key_with_repeat int key_can_repeat(int key) { int k = 0; for (;k < boardNumRepeatableKeys; ++k) { if (boardRepeatableKeys[k] == key) { break; } } if (k < boardNumRepeatableKeys) return 1; return 0; } int ui_wait_key_with_repeat() { int key = -1; // Loop to wait for more keys. do { struct timeval now; struct timespec timeout; Loading @@ -901,53 +915,71 @@ int ui_wait_key_with_repeat() timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC; int rc = 0; while (key_queue_len == 0 && rc != ETIMEDOUT) { pthread_mutex_lock(&key_queue_mutex); while (key_queue_len == 0 && rc != ETIMEDOUT) { rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); } pthread_mutex_unlock(&key_queue_mutex); if (rc == ETIMEDOUT && !usb_connected()) { return -1; } if (rc == ETIMEDOUT && !usb_connected()) return -1; while (key_queue_len > 0) { // Loop to wait wait for more keys, or repeated keys to be ready. while (1) { unsigned long now_msec; usleep(1); gettimeofday(&now, NULL); now_msec = (now.tv_sec * 1000) + (now.tv_usec / 1000); key = key_queue[0]; pthread_mutex_lock(&key_queue_mutex); memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); pthread_mutex_unlock(&key_queue_mutex); if (!key_pressed[key]) { if (key_last_repeat[key] > 0) continue; else return key; // 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; } int k = 0; for (;k < boardNumRepeatableKeys; ++k) { if (boardRepeatableKeys[k] == key) { 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 (k < boardNumRepeatableKeys) { 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) || } 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 if (key_last_repeat[key] > 0) { } else { // Not ready pthread_mutex_unlock(&key_queue_mutex); continue; } } pthread_mutex_unlock(&key_queue_mutex); return key; } } while (key_queue_len == 0); } while (1); return key; } Loading