static int do_cancel(Camera *camera, GPContext *context) { int r; struct tf_packet reply; r = send_cancel(camera,context); if(r < 0) return r; r = get_tf_packet(camera, &reply, context); if(r < 0) return r; switch (get_u32(&reply.cmd)) { case SUCCESS: gp_log (GP_LOG_DEBUG, "topfield", "In progress operation cancelled\n"); return GP_OK; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet\n"); break; } return GP_ERROR_IO; }
int do_cmd_reset(int fd) { int r; r = send_cmd_reset(fd); if(r < 0) { return -EPROTO; } r = get_tf_packet(fd, &reply); if(r < 0) { return -EPROTO; } switch (get_u32(&reply.cmd)) { case SUCCESS: printf("TF5000PVRt should now reboot\n"); return 0; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); } return -EPROTO; }
static int delete_file_func (CameraFilesystem *fs, const char *folder, const char *filename, void *data, GPContext *context) { Camera *camera = data; int r; char *path = get_path (camera, folder, filename); struct tf_packet reply; r = send_cmd_hdd_del(camera, path, context); free (path); if(r < 0) return r; r = get_tf_packet(camera, &reply, context); if(r < 0) return r; switch (get_u32(&reply.cmd)) { case SUCCESS: return GP_OK; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet\n"); break; } return GP_ERROR_IO; }
static int do_hdd_rename(Camera *camera, char *srcPath, char *dstPath, GPContext *context) { int r; struct tf_packet reply; r = send_cmd_hdd_rename(camera, srcPath, dstPath, context); if(r < 0) return r; r = get_tf_packet(camera, &reply, context); if(r < 0) return r; switch (get_u32(&reply.cmd)) { case SUCCESS: return GP_OK; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet\n"); break; } return GP_ERROR_IO; }
int do_cancel(int fd) { int r; r = send_cancel(fd); if(r < 0) { return -EPROTO; } r = get_tf_packet(fd, &reply); if(r < 0) { return -EPROTO; } switch (get_u32(&reply.cmd)) { case SUCCESS: printf("In progress operation cancelled\n"); return 0; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); } return -EPROTO; }
int do_cmd_ready(int fd) { int r; r = send_cmd_ready(fd); if(r < 0) { return -EPROTO; } r = get_tf_packet(fd, &reply); if(r < 0) { return -EPROTO; } switch (get_u32(&reply.cmd)) { case SUCCESS: printf("Device reports ready.\n"); return 0; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); get_u32(&reply.data); break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); return -1; } return -EPROTO; }
int do_hdd_mkdir(int fd, char *path) { int r; r = send_cmd_hdd_create_dir(fd, path); if(r < 0) { return -EPROTO; } r = get_tf_packet(fd, &reply); if(r < 0) { return -EPROTO; } switch (get_u32(&reply.cmd)) { case SUCCESS: return 0; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); } return -EPROTO; }
static int storage_info_func (CameraFilesystem *fs, CameraStorageInformation **storageinformations, int *nrofstorageinformations, void *data, GPContext *context) { Camera *camera = data; int r; struct tf_packet reply; CameraStorageInformation *sif; /* List your storages here */ gp_log (GP_LOG_ERROR, "topfield", __func__); r = send_cmd_hdd_size(camera,context); if(r < 0) return r; r = get_tf_packet(camera, &reply, context); if(r < 0) return r; switch (get_u32(&reply.cmd)) { case DATA_HDD_SIZE: { unsigned int totalk = get_u32(&reply.data); unsigned int freek = get_u32(&reply.data[4]); sif = *storageinformations = calloc(sizeof(CameraStorageInformation),1); *nrofstorageinformations = 1; sif->fields |= GP_STORAGEINFO_BASE; strcpy (sif->basedir,"/"); sif->fields |= GP_STORAGEINFO_STORAGETYPE; sif->type = GP_STORAGEINFO_ST_FIXED_RAM; sif->fields |= GP_STORAGEINFO_ACCESS; sif->access = GP_STORAGEINFO_AC_READWRITE; sif->fields |= GP_STORAGEINFO_FILESYSTEMTYPE; sif->fstype = GP_STORAGEINFO_FST_GENERICHIERARCHICAL; sif->fields |= GP_STORAGEINFO_MAXCAPACITY; sif->capacitykbytes = totalk / 1024; sif->fields |= GP_STORAGEINFO_FREESPACEKBYTES; sif->freekbytes = freek / 1024; return GP_OK; break; } case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet\n"); break; } return GP_ERROR_IO; }
int do_hdd_size(int fd) { int r; r = send_cmd_hdd_size(fd); if(r < 0) { return -EPROTO; } r = get_tf_packet(fd, &reply); if(r < 0) { return -EPROTO; } switch (get_u32(&reply.cmd)) { case DATA_HDD_SIZE: { __u32 totalk = get_u32(&reply.data); __u32 freek = get_u32(&reply.data[4]); printf("Total %10u kiB %7u MiB %4u GiB\n", totalk, totalk / 1024, totalk / (1024 * 1024)); printf("Free %10u kiB %7u MiB %4u GiB\n", freek, freek / 1024, freek / (1024 * 1024)); return 0; break; } case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); } return -EPROTO; }
int do_cmd_turbo(int fd, char *state) { int r; int turbo_on = atoi(state); if(0 == strcasecmp("ON", state)) { turbo_on = 1; } r = send_cmd_turbo(fd, turbo_on); if(r < 0) { return -EPROTO; } r = get_tf_packet(fd, &reply); if(r < 0) { return -EPROTO; } switch (get_u32(&reply.cmd)) { case SUCCESS: trace(1, fprintf(stderr, "Turbo mode: %s\n", turbo_on ? "ON" : "OFF")); return 0; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); } return -EPROTO; }
static int do_cmd_turbo(Camera *camera, char *state, GPContext *context) { int r; int turbo_on = atoi(state); struct tf_packet reply; char buf[1024]; /* check if we want to use turbo mode. Default is YES */ if (GP_OK == gp_setting_get("topfield","turbo", buf)) if (!strcmp(buf,"no")) return GP_OK; if(0 == strcasecmp("ON", state)) turbo_on = 1; r = send_cmd_turbo(camera, turbo_on, context); if(r < 0) return r; r = get_tf_packet(camera, &reply, context); if(r < 0) return r; switch (get_u32(&reply.cmd)) { case SUCCESS: gp_log (GP_LOG_DEBUG, "topfield", "Turbo mode: %s\n", turbo_on ? "ON" : "OFF"); return GP_OK; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet\n"); } return GP_ERROR_IO; }
static int get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileInfo *info, void *data, GPContext *context) { Camera *camera = data; int r; struct tf_packet reply; char *xfolder = strdup (folder); backslash (xfolder); r = send_cmd_hdd_dir(camera, xfolder, context); free (xfolder); if(r < GP_OK) return r; while(0 < get_tf_packet(camera, &reply, context)) { switch (get_u32(&reply.cmd)) { case DATA_HDD_DIR: decode_and_get_info(camera, folder, &reply, filename, info, context); send_success(camera,context); break; case DATA_HDD_DIR_END: return GP_OK; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); return GP_ERROR_IO; break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet\n"); return GP_ERROR_IO; } } return GP_OK; }
int do_hdd_dir(int fd, char *path) { int r; r = send_cmd_hdd_dir(fd, path); if(r < 0) { return -EPROTO; } while(0 < get_tf_packet(fd, &reply)) { switch (get_u32(&reply.cmd)) { case DATA_HDD_DIR: decode_dir(&reply); send_success(fd); break; case DATA_HDD_DIR_END: return 0; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); return -EPROTO; break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); return -EPROTO; } } return -EPROTO; }
static int put_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFile *file, void *data, GPContext *context) { Camera *camera = data; /* * Upload the file to the camera. Use gp_file_get_data_and_size etc. */ int result = -EPROTO; time_t startTime = time(NULL); enum { START, DATA, END, FINISHED } state; int src = -1; int r; int update = 0; struct stat srcStat; __u64 fileSize; __u64 byteCount = 0; const char *filename; char *path; struct tf_packet reply; if(0 != fstat(src, &srcStat)) { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Can not examine source file: %s\n", strerror(errno)); result = errno; goto out; } fileSize = srcStat.st_size; if(fileSize == 0) { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Source file is empty - not transfering.\n"); result = -ENODATA; goto out; } path = get_path (camera, folder, filename); r = send_cmd_hdd_file_send(camera, PUT, path, context); if(r < 0) goto out; state = START; while(0 < get_tf_packet(camera, &reply, context)) { update = (update + 1) % 16; switch (get_u32(&reply.cmd)) { case SUCCESS: switch (state) { case START: { /* Send start */ struct typefile *tf = (struct typefile *) packet.data; put_u16(&packet.length, PACKET_HEAD_SIZE + 114); put_u32(&packet.cmd, DATA_HDD_FILE_START); time_to_tfdt(srcStat.st_mtime, &tf->stamp); tf->filetype = 2; put_u64(&tf->size, srcStat.st_size); strncpy((char *) tf->name, path, 94); tf->name[94] = '\0'; tf->unused = 0; tf->attrib = 0; gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_START\n", __func__); r = send_tf_packet(camera, &packet, context); if(r < 0) { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n"); goto out; } state = DATA; break; } case DATA: { int payloadSize = sizeof(packet.data) - 9; ssize_t w = read(src, &packet.data[8], payloadSize); /* Detect a Topfield protcol bug and prevent the sending of packets that are a multiple of 512 bytes. */ if((w > 4) && (((((PACKET_HEAD_SIZE + 8 + w) + 1) & ~1) % 0x200) == 0)) { lseek(src, -4, SEEK_CUR); w -= 4; payloadSize -= 4; } put_u16(&packet.length, PACKET_HEAD_SIZE + 8 + w); put_u32(&packet.cmd, DATA_HDD_FILE_DATA); put_u64(packet.data, byteCount); byteCount += w; /* Detect EOF and transition to END */ if((w < 0) || (byteCount >= fileSize)) { state = END; } if(w > 0) { gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_DATA\n", __func__); r = send_tf_packet(camera, &packet, context); if(r < w) { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n"); goto out; } } if(!update && !quiet) { progressStats(fileSize, byteCount, startTime); } break; } case END: /* Send end */ put_u16(&packet.length, PACKET_HEAD_SIZE); put_u32(&packet.cmd, DATA_HDD_FILE_END); gp_log (GP_LOG_DEBUG, "topfield", "%s: DATA_HDD_FILE_END\n", __func__); r = send_tf_packet(camera, &packet, context); if(r < 0) { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Incomplete send.\n"); goto out; } state = FINISHED; break; case FINISHED: result = 0; goto out; break; } break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); goto out; break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet (%d)\n", get_u32(&reply.cmd)); break; } } finalStats(byteCount, startTime); out: close(src); return result; }
static int get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileType type, CameraFile *file, void *data, GPContext *context) { Camera *camera = data; int result = GP_ERROR_IO; enum { START, DATA, ABORT } state; int r, pid = 0, update = 0; uint64_t byteCount = 0; struct utimbuf mod_utime_buf = { 0, 0 }; char *path; struct tf_packet reply; if (type != GP_FILE_TYPE_NORMAL) return GP_ERROR_NOT_SUPPORTED; do_cmd_turbo (camera, "ON", context); path = get_path(camera, folder, filename); r = send_cmd_hdd_file_send(camera, GET, path, context); free (path); if(r < 0) goto out; state = START; while(0 < (r = get_tf_packet(camera, &reply, context))) { update = (update + 1) % 4; switch (get_u32(&reply.cmd)) { case DATA_HDD_FILE_START: if(state == START) { struct typefile *tf = (struct typefile *) reply.data; byteCount = get_u64(&tf->size); pid = gp_context_progress_start (context, byteCount, _("Downloading %s..."), filename); mod_utime_buf.actime = mod_utime_buf.modtime = tfdt_to_time(&tf->stamp); send_success(camera,context); state = DATA; } else { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_START packet in state %d\n", state); send_cancel(camera,context); state = ABORT; } break; case DATA_HDD_FILE_DATA: if(state == DATA) { uint64_t offset = get_u64(reply.data); uint16_t dataLen = get_u16(&reply.length) - (PACKET_HEAD_SIZE + 8); int w; if (!update) { /* avoid doing it too often */ gp_context_progress_update (context, pid, offset + dataLen); if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) { send_cancel(camera,context); state = ABORT; } } if(r < get_u16(&reply.length)) { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Short packet %d instead of %d\n", r, get_u16(&reply.length)); /* TODO: Fetch the rest of the packet */ } w = gp_file_append (file, (char*)&reply.data[8], dataLen); if(w < GP_OK) { /* Can't write data - abort transfer */ gp_log (GP_LOG_ERROR, "topfield", "ERROR: Can not write data: %d\n", w); send_cancel(camera,context); state = ABORT; } } else { gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unexpected DATA_HDD_FILE_DATA packet in state %d\n", state); send_cancel(camera,context); state = ABORT; } break; case DATA_HDD_FILE_END: send_success(camera,context); result = GP_OK; goto out; break; case FAIL: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Device reports %s\n", decode_error(&reply)); send_cancel(camera,context); state = ABORT; break; case SUCCESS: goto out; break; default: gp_log (GP_LOG_ERROR, "topfield", "ERROR: Unhandled packet (cmd 0x%x)\n", get_u32(&reply.cmd)); break; } } if (pid) gp_context_progress_stop (context, pid); out: do_cmd_turbo (camera, "OFF", context); return result; }
int do_hdd_file_put(int fd, char *srcPath, char *dstPath) { int result = -EPROTO; time_t startTime = time(NULL); enum { START, DATA, END, FINISHED } state; int src = -1; int r; int update = 0; struct stat64 srcStat; __u64 fileSize; __u64 byteCount = 0; trace(4, fprintf(stderr, "%s\n", __func__)); src = open64(srcPath, O_RDONLY); if(src < 0) { fprintf(stderr, "ERROR: Can not open source file: %s\n", strerror(errno)); return errno; } if(0 != fstat64(src, &srcStat)) { fprintf(stderr, "ERROR: Can not examine source file: %s\n", strerror(errno)); result = errno; goto out; } fileSize = srcStat.st_size; if(fileSize == 0) { fprintf(stderr, "ERROR: Source file is empty - not transfering.\n"); result = -ENODATA; goto out; } r = send_cmd_hdd_file_send(fd, PUT, dstPath); if(r < 0) { goto out; } state = START; while(0 < get_tf_packet(fd, &reply)) { update = (update + 1) % 16; switch (get_u32(&reply.cmd)) { case SUCCESS: switch (state) { case START: { /* Send start */ struct typefile *tf = (struct typefile *) packet.data; put_u16(&packet.length, PACKET_HEAD_SIZE + 114); put_u32(&packet.cmd, DATA_HDD_FILE_START); time_to_tfdt(srcStat.st_mtime, &tf->stamp); tf->filetype = 2; put_u64(&tf->size, srcStat.st_size); strncpy((char *) tf->name, dstPath, 94); tf->name[94] = '\0'; tf->unused = 0; tf->attrib = 0; trace(3, fprintf(stderr, "%s: DATA_HDD_FILE_START\n", __func__)); r = send_tf_packet(fd, &packet); if(r < 0) { fprintf(stderr, "ERROR: Incomplete send.\n"); goto out; } state = DATA; break; } case DATA: { int payloadSize = sizeof(packet.data) - 9; ssize_t w = read(src, &packet.data[8], payloadSize); /* Detect a Topfield protcol bug and prevent the sending of packets that are a multiple of 512 bytes. */ if((w > 4) && (((((PACKET_HEAD_SIZE + 8 + w) + 1) & ~1) % 0x200) == 0)) { lseek64(src, -4, SEEK_CUR); w -= 4; payloadSize -= 4; } put_u16(&packet.length, PACKET_HEAD_SIZE + 8 + w); put_u32(&packet.cmd, DATA_HDD_FILE_DATA); put_u64(packet.data, byteCount); byteCount += w; /* Detect EOF and transition to END */ if((w < 0) || (byteCount >= fileSize)) { state = END; } if(w > 0) { trace(3, fprintf(stderr, "%s: DATA_HDD_FILE_DATA\n", __func__)); r = send_tf_packet(fd, &packet); if(r < w) { fprintf(stderr, "ERROR: Incomplete send.\n"); goto out; } } if(!update && !quiet) { progressStats(fileSize, byteCount, startTime); } break; } case END: /* Send end */ put_u16(&packet.length, PACKET_HEAD_SIZE); put_u32(&packet.cmd, DATA_HDD_FILE_END); trace(3, fprintf(stderr, "%s: DATA_HDD_FILE_END\n", __func__)); r = send_tf_packet(fd, &packet); if(r < 0) { fprintf(stderr, "ERROR: Incomplete send.\n"); goto out; } state = FINISHED; break; case FINISHED: result = 0; goto out; break; } break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); goto out; break; default: fprintf(stderr, "ERROR: Unhandled packet\n"); break; } } finalStats(byteCount, startTime); out: close(src); return result; }
int do_hdd_file_get(int fd, char *srcPath, char *dstPath) { int result = -EPROTO; time_t startTime = time(NULL); enum { START, DATA, ABORT } state; int dst = -1; int r; int update = 0; __u64 byteCount = 0; struct utimbuf mod_utime_buf = { 0, 0 }; dst = open64(dstPath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if(dst < 0) { fprintf(stderr, "ERROR: Can not open destination file: %s\n", strerror(errno)); return errno; } r = send_cmd_hdd_file_send(fd, GET, srcPath); if(r < 0) { goto out; } state = START; while(0 < (r = get_tf_packet(fd, &reply))) { update = (update + 1) % 16; switch (get_u32(&reply.cmd)) { case DATA_HDD_FILE_START: if(state == START) { struct typefile *tf = (struct typefile *) reply.data; byteCount = get_u64(&tf->size); mod_utime_buf.actime = mod_utime_buf.modtime = tfdt_to_time(&tf->stamp); send_success(fd); state = DATA; } else { fprintf(stderr, "ERROR: Unexpected DATA_HDD_FILE_START packet in state %d\n", state); send_cancel(fd); state = ABORT; } break; case DATA_HDD_FILE_DATA: if(state == DATA) { __u64 offset = get_u64(reply.data); __u16 dataLen = get_u16(&reply.length) - (PACKET_HEAD_SIZE + 8); ssize_t w; if(!update && !quiet) { progressStats(byteCount, offset + dataLen, startTime); } if(r < get_u16(&reply.length)) { fprintf(stderr, "ERROR: Short packet %d instead of %d\n", r, get_u16(&reply.length)); /* TODO: Fetch the rest of the packet */ } w = write(dst, &reply.data[8], dataLen); if(w < dataLen) { /* Can't write data - abort transfer */ fprintf(stderr, "ERROR: Can not write data: %s\n", strerror(errno)); send_cancel(fd); state = ABORT; } } else { fprintf(stderr, "ERROR: Unexpected DATA_HDD_FILE_DATA packet in state %d\n", state); send_cancel(fd); state = ABORT; } break; case DATA_HDD_FILE_END: send_success(fd); result = 0; goto out; break; case FAIL: fprintf(stderr, "ERROR: Device reports %s\n", decode_error(&reply)); send_cancel(fd); state = ABORT; break; case SUCCESS: goto out; break; default: fprintf(stderr, "ERROR: Unhandled packet (cmd 0x%x)\n", get_u32(&reply.cmd)); } } utime(dstPath, &mod_utime_buf); finalStats(byteCount, startTime); out: close(dst); return result; }