/* cache.c * * Copyright 2020 Ondrej Zary * based on Docupen tools by Florian Heinz */ #include #include #include "docupen.h" static char cmd_datalen[] = { 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a }; static char cmd_unknown[] = { 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a }; static char cmd_get_all[] = { 0x51, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1a }; static bool fill_cache(Camera *camera) { char *buf; int ret; size_t pktsize = camera->pl->info.packetsize[2] | camera->pl->info.packetsize[1] << 8| camera->pl->info.packetsize[0] << 16; buf = malloc(pktsize); if (!buf) return false; /* truncate file */ fclose(camera->pl->cache); camera->pl->cache = fopen(camera->pl->cache_file, "w+"); if (!camera->pl->cache) { perror("fopen"); GP_LOG_E("unable to trunate cache file %s", camera->pl->cache_file); free(buf); return false; } dp_cmd(camera->port, cmd_unknown); dp_cmd(camera->port, cmd_get_all); uint32_t done = 0; while (done < camera->pl->datalen) { ret = gp_port_read(camera->port, buf, (camera->pl->datalen - done < pktsize) ? camera->pl->datalen-done : pktsize); if (ret < 0) break; fwrite(buf, 1, ret, camera->pl->cache); done += ret; if ((size_t)ret < pktsize) break; } free(buf); return true; } bool dp_init_cache(Camera *camera) { if (camera->pl->cache_file) return true; camera->pl->cache_file = malloc(64 + strlen(getenv("HOME"))); if (!camera->pl->cache_file) return false; sprintf(camera->pl->cache_file, "%s/.cache", getenv("HOME")); if (!gp_system_is_dir(camera->pl->cache_file) && gp_system_mkdir(camera->pl->cache_file) != GP_OK) { GP_LOG_E("unable to create directory %s", camera->pl->cache_file); goto err_free; } sprintf(camera->pl->cache_file, "%s/.cache/docupen-%s.bin", getenv("HOME"), camera->pl->info.serialno); camera->pl->cache = fopen(camera->pl->cache_file, "a+"); if (!camera->pl->cache) { perror("fopen"); GP_LOG_E("unable to open cache file %s", camera->pl->cache_file); goto err_free; } dp_cmd(camera->port, cmd_datalen); gp_port_read(camera->port, (void *)&camera->pl->datalen, sizeof(camera->pl->datalen)); camera->pl->datalen = le32toh(camera->pl->datalen); fseek(camera->pl->cache, 0, SEEK_END); if (ftell(camera->pl->cache) == camera->pl->datalen) { /* cache is valid */ if (!dp_init_calibration(camera, false)) goto err_free; return true; } if (!dp_init_calibration(camera, true)) /* if cache is invalid, update LUT too */ goto err_free; if (fill_cache(camera)) return true; err_free: free(camera->pl->cache_file); camera->pl->cache_file = NULL; return false; } bool dp_delete_cache(Camera *camera) { if (camera->pl->cache) fclose(camera->pl->cache); camera->pl->cache = NULL; return !unlink(camera->pl->cache_file); }