static void decode_and_get_info(Camera *camera, const char *folder, struct tf_packet *p, const char *fn, CameraFileInfo *info, GPContext *context) { unsigned short count = (get_u16(&p->length) - PACKET_HEAD_SIZE) / sizeof(struct typefile); struct typefile *entries = (struct typefile *) p->data; int i; char *name; for(i = 0; i < count; i++) { switch (entries[i].filetype) { case 1: break;/*dir*/ case 2: /* file */ name = _convert_and_logname (camera, (char*)entries[i].name); if (!strcmp (name, fn)) { /* the wanted current one */ memset (info, 0, sizeof (*info)); info->file.fields = GP_FILE_INFO_SIZE|GP_FILE_INFO_MTIME; if (strstr (name, ".rec")) { info->file.fields |= GP_FILE_INFO_TYPE; strcpy (info->file.type, GP_MIME_MPEG); } info->file.size = get_u64(&entries[i].size); info->file.mtime = tfdt_to_time(&entries[i].stamp); } else { /* cache the others to avoid further turnarounds */ CameraFileInfo xinfo; memset (&xinfo, 0, sizeof (xinfo)); xinfo.file.fields = GP_FILE_INFO_TYPE|GP_FILE_INFO_SIZE|GP_FILE_INFO_MTIME; strcpy (xinfo.file.type, GP_MIME_MPEG); xinfo.file.size = get_u64(&entries[i].size); xinfo.file.mtime = tfdt_to_time(&entries[i].stamp); gp_filesystem_append (camera->fs, folder, name, context); /* FIXME: might fail if exist? */ gp_filesystem_set_info_noop (camera->fs, folder, name, xinfo, context); } break; default: break; } #if 0 /* This makes the assumption that the timezone of the Toppy and the system * that puppy runs on are the same. Given the limitations on the length of * USB cables, this condition is likely to be satisfied. */ timestamp = tfdt_to_time(&entries[i].stamp); printf("%c %20llu %24.24s %s\n", type, get_u64(&entries[i].size), ctime(×tamp), entries[i].name); #endif } }
void decode_dir(struct tf_packet *p) { __u16 count = (get_u16(&p->length) - PACKET_HEAD_SIZE) / sizeof(struct typefile); struct typefile *entries = (struct typefile *) p->data; int i; time_t timestamp; if (xml) { printf("<?xml version=\"1.0\" encoding=\"ISO-8859-15\"?>\r\n\r\n"); printf("<contents>\n"); } for(i = 0; (i < count); i++) { /* This makes the assumption that the timezone of the Toppy and the system * that puppy runs on are the same. Given the limitations on the length of * USB cables, this condition is likely to be satisfied. */ struct tm tm; timestamp = tfdt_to_time(&entries[i].stamp); tm = *localtime(×tamp); if (xml) { int ft = entries[i].filetype; printf("<file type=\"%s\" size=\"%llu\" time=\"%04d-%02d-%02d %d:%02d:%02d\" name=\"%W\"/>\n", ft == 1 ? "dir" : ft == 2 ? "file" : "unknown", get_u64(&entries[i].size), tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, entries[i].name); } else { char type; switch (entries[i].filetype) { case 1: type = 'd'; break; case 2: type = 'f'; break; default: type = '?'; } printf("%c %20llu %24.24s %s\n", type, get_u64(&entries[i].size), ctime(×tamp), entries[i].name); } } if (xml) { printf("</contents>\n"); } }
static void decode_dir(Camera *camera, struct tf_packet *p, int listdirs, CameraList *list) { unsigned short count = (get_u16(&p->length) - PACKET_HEAD_SIZE) / sizeof(struct typefile); struct typefile *entries = (struct typefile *) p->data; int i; char *name; for(i = 0; i < count; i++) { switch (entries[i].filetype) { case 1: if (listdirs) { if (!strcmp ((char*)entries[i].name, "..")) continue; gp_list_append (list, (char*)entries[i].name, NULL); } break; case 2: if (!listdirs) { name = _convert_and_logname (camera, (char*)entries[i].name); gp_list_append (list, name, NULL); } break; default: break; } #if 0 /* This makes the assumption that the timezone of the Toppy and the system * that puppy runs on are the same. Given the limitations on the length of * USB cables, this condition is likely to be satisfied. */ timestamp = tfdt_to_time(&entries[i].stamp); printf("%c %20llu %24.24s %s\n", type, get_u64(&entries[i].size), ctime(×tamp), entries[i].name); #endif } }
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_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; }