diff --git a/eyefi-config.c b/eyefi-config.c index e70748a..382d1ca 100755 --- a/eyefi-config.c +++ b/eyefi-config.c @@ -9,6 +9,7 @@ */ #include "eyefi-config.h" +#include int eyefi_debug_level = 1; @@ -181,7 +182,7 @@ void init_card() eyefi_seq.seq = 0x1234; eyefi_seq.seq++; debug_printf(2, "Done initializing card...\n"); - debug_printf(2, "seq was: %04x\n", eyefi_seq.seq); + debug_printf(3, "seq was: %04x\n", eyefi_seq.seq); } static char *eyefi_file(enum eyefi_file file) @@ -190,11 +191,63 @@ static char *eyefi_file(enum eyefi_file file) return eyefi_file_on(file, locate_eyefi_mount()); } +int majflts(void) +{ + static char buf[1000]; + static char garb[1000]; + int min_flt; + int cmin_flt; + int maj_flt; + int cmaj_flt; + int gi; + int fd; + + // touch it beforehand so it doesn't fault + memset(buf, 0, 1000); + memset(garb, 0, 1000); + + fd = open("/proc/self/stat", O_RDONLY); + read(fd, buf, 1000); + sscanf(buf, "%d %s %s %d %d %d %d %d %d %d %d %d %d %s", + &gi, garb, garb, &gi, &gi, &gi, &gi, &gi, &gi, + &min_flt, &cmin_flt, &maj_flt, &cmaj_flt, + garb); + //printf("%d %d %d %d\n", min_flt, cmin_flt, maj_flt, cmaj_flt); + close(fd); + return maj_flt+cmaj_flt; +} + +// How many pages just came in from the disk? +int nr_fresh_pages(int fd, int len) +{ + int PAGE_SIZE = getpagesize(); + int faults_before; + int faults_after; + char *addr; + int tmp; + int i; + + addr = mmap(NULL, len, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0); + //intf("addr: %p\n", addr); + faults_before = majflts(); + for (i = 0; i < len; i += PAGE_SIZE) { + tmp += addr[i]; + } + faults_after = majflts(); + munmap(addr, len); + debug_printf(3, "%s(%d) faults_before: %d faults_after: %d net: %d\n", + __func__, fd, + faults_before, faults_after, (faults_after - faults_before)); + return (faults_after - faults_before); +} + void read_from(enum eyefi_file __file) { + int tries = 0; int ret; int fd; char *file = eyefi_file(__file); + int nr_fresh; init_card(); @@ -203,9 +256,26 @@ retry: if (fd < 0) open_error(file, fd); fd_flush(fd); + // fd_flush() does not appear to be working 100% of the + // time. It is not working on my Thinkpad, but works + // fine on the same kernel on the Ideapad. Bizarre. + // This at least works around it by detecting when we + // did and did not actually bring in pages from the + // disk. + nr_fresh = nr_fresh_pages(fd, EYEFI_BUF_SIZE); + if (!nr_fresh) { + tries++; + debug_printf(2, "fd_flush(%d) was unsuccessful(%d), retrying (%d)...\n", + fd, nr_fresh_pages, tries); + close(fd); + goto retry; + } ret = read(fd, eyefi_buf, EYEFI_BUF_SIZE); - if (eyefi_debug_level >= 3) + if ((eyefi_debug_level >= 3) || + (eyefi_debug_level >= 2 && (__file == RSPM))) { + printf("%s:", eyefi_file_name(__file)); dumpbuf(eyefi_buf, 128); + } if (ret < 0) { close(fd); perror("bad read, retrying..."); @@ -248,17 +318,16 @@ void write_to(enum eyefi_file __file, void *stuff, int len) if (len == -1) len = strlen(stuff); - if (eyefi_debug_level >= 3) { - debug_printf(3, "%s('%s', ..., %d)\n", __func__, file, len); - dumpbuf(stuff, len); - } memset(eyefi_buf, 0, EYEFI_BUF_SIZE); memcpy(eyefi_buf, stuff, len); fd = open(file, O_RDWR|O_CREAT, 0600); if (fd < 0 ) open_error(file, fd); - if (eyefi_debug_level > 3) + if ((eyefi_debug_level >= 3) || + (eyefi_debug_level >= 2 && (__file == REQM))) { + printf("%s:", eyefi_file_name(__file)); dumpbuf(eyefi_buf, 128); + } wrote = write(fd, eyefi_buf, EYEFI_BUF_SIZE); if (wrote < 0) open_error(file, wrote); @@ -579,7 +648,7 @@ int config_int_get(enum card_info_subcommand subcommand) struct var_byte_response *rsp; card_info_cmd(subcommand); rsp = eyefi_buf; - return rsp->bytes[0]; + return (rsp->bytes[0] & 0xff); } void wlan_disable(int do_disable) @@ -651,6 +720,63 @@ void print_transfer_status(void) zero_card_files(); } +#define DIRECT_WAIT_FOREVER ((u8)0xff) + +/* obviously not thread safe with a static buffer */ +char *secsprint(int secs) +{ + static char buffer[] = "indefinitely"; + if (secs == DIRECT_WAIT_FOREVER) + sprintf(buffer, "indefinitely"); + else + sprintf(buffer, "%d seconds", secs); + return buffer; +} + +void print_direct_status(void) +{ + int wait_for_secs = config_int_get(DIRECT_WAIT_FOR_CONNECTION); + int wait_after_secs = config_int_get(DIRECT_WAIT_AFTER_TRANSFER); + + printf("Direct mode is: "); + if (!wait_for_secs) { + printf("disabled\n"); + return; + } + printf("enabled\n"); + printf("The Direct Mode network will:\n"); + printf("\twait for %s for a device to connect\n", secsprint(wait_for_secs)); + printf("\twill stay on %s after the last item is received\n", secsprint(wait_after_secs)); +} + +int disable_direct_mode(void) +{ + // DIRECT_WAIT_FOR_CONNECTION=0 appears to be the trigger + // to keep direct mode on and off. But, no matter what + // DIRECT_WAIT_AFTER_TRANSFER was set to before the mode + // is disabled, the official software seems to set it to + // 60 seconds during a disable operation + config_int_set(DIRECT_WAIT_FOR_CONNECTION, 0); + config_int_set(DIRECT_WAIT_AFTER_TRANSFER, 60); +} + +int enable_direct_mode(int wait_for_secs, int wait_after_secs) +{ + config_int_set(DIRECT_WAIT_FOR_CONNECTION, wait_for_secs); + config_int_set(DIRECT_WAIT_AFTER_TRANSFER, wait_after_secs); + print_direct_status(); +} + +int start_direct(void) +{ + int ret; + debug_printf(2, "%s()\n", __func__); + ret = issue_noarg_command('S'); + printf("AP started (%d)\n", ret); + return ret; +} + + struct testbuf { char cmd; u8 l1; @@ -683,6 +809,12 @@ void testit0(void) int i; int fdin; int fdout; + + start_direct(); + print_direct_status(); + //disable_direct_mode(); + //print_direct_status(); + exit(0); //char new_cmd[] = {'O', 0x06, 0x0d, 0x0a, 0x31, 0x30, 0x2e, 0x36, 0x2e, 0x30, 0x2e, 0x31, 0x33, 0x37}; //printf("waiting...\n"); diff --git a/eyefi-config.h b/eyefi-config.h index 9649fe2..e4ed688 100644 --- a/eyefi-config.h +++ b/eyefi-config.h @@ -178,8 +178,9 @@ enum card_info_subcommand { UPLOAD_STATUS = 14, // current uploading file info UNKNOWN_15 = 15, // always returns {0x01, 0x1d} as far as I've seen TRANSFER_MODE = 17, - ENDLESS = 27, + DIRECT_WAIT_FOR_CONNECTION = 0x24, // 0 == "direct mode off" + DIRECT_WAIT_AFTER_TRANSFER = 0x25, // set to 60 when direct mode off UNKNOWN_ff = 0xff, // The D90 does this, and it looks to // return a 1-byte response length // followed by a number of 8-byte responses diff --git a/eyefi-linux.c b/eyefi-linux.c index 0ed49fd..37e481e 100644 --- a/eyefi-linux.c +++ b/eyefi-linux.c @@ -57,6 +57,8 @@ static char *replace_escapes(char *str) int fd_flush(int fd) { int ret; + fsync(fd); + fdatasync(fd); ret = posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); if (ret) perror("posix_fadvise() failed");