int send_cmd_hdd_file_send_with_offset(libusb_device_handle* fd, __u8 dir, char *path, __u64 offset) { struct tf_packet req; __u16 packetSize, pad; int pathLen = strlen(path) + 1; trace(3, printf("send_cmd_hdd_file_send_with_offset: %s [%ld]\n",path,offset)); if((PACKET_HEAD_SIZE + 1 + 2 + pathLen) >= MAXIMUM_PACKET_SIZE) { fprintf(stdout, "ERROR: Path is too long.\n"); return -1; } packetSize = PACKET_HEAD_SIZE + 1 + 2 + pathLen +8; pad = ((packetSize + 1) & ~1 ) - packetSize; //printf("Packet padding: %d\n",pad); pad = 0;//((packetSize + 1) & ~1 ) - packetSize; //printf("Packet padding: %d\n",pad); packetSize +=pad; put_u16(&req.length, packetSize); put_u32(&req.cmd, CMD_HDD_FILE_SEND); req.data[0] = dir; put_u16(&req.data[1], (__u16) pathLen); strcpy((char *) &req.data[3], path); put_u64( &req.data[3+pathLen+pad],offset); return send_tf_packet(fd, &req); }
int send_cmd_hdd_rename(libusb_device_handle* fd, char *src, char *dst) { struct tf_packet req; __u16 packetSize; __u16 srcLen = strlen(src) + 1; __u16 dstLen = strlen(dst) + 1; trace(3, printf("send_cmd_hdd_rename: %s : %s\n",src,dst)); if((PACKET_HEAD_SIZE + 2 + srcLen + 2 + dstLen) >= MAXIMUM_PACKET_SIZE) { fprintf(stdout, "ERROR: Combination of source and destination paths is too long.\n"); return -1; } packetSize = PACKET_HEAD_SIZE + 2 + srcLen + 2 + dstLen; packetSize = (packetSize + 1) & ~1; put_u16(&req.length, packetSize); put_u32(&req.cmd, CMD_HDD_RENAME); put_u16(&req.data[0], srcLen); strcpy((char *) &req.data[2], src); put_u16(&req.data[2 + srcLen], dstLen); strcpy((char *) &req.data[2 + srcLen + 2], dst); return send_tf_packet(fd, &req); }
int send_cmd_reset(libusb_device_handle* fd) { struct tf_packet req; trace(3, printf("send_cmd_reset\n")); put_u16(&req.length, 8); put_u32(&req.cmd, CMD_RESET); return send_tf_packet(fd, &req); }
int send_cmd_hdd_size(libusb_device_handle* fd) { struct tf_packet req; trace(3, printf("send_cmd_hdd_size\n")); put_u16(&req.length, 8); put_u32(&req.cmd, CMD_HDD_SIZE); return send_tf_packet(fd, &req); }
int send_cmd_turbo(libusb_device_handle* fd, int turbo_on) { struct tf_packet req; trace(3, printf("send_cmd_turbo\n")); put_u16(&req.length, 12); put_u32(&req.cmd, CMD_TURBO); put_u32(&req.data, turbo_on); return send_tf_packet(fd, &req); }
ssize_t send_cmd_hdd_size(int fd) { struct tf_packet req; trace(2, fprintf(stderr, "%s\n", __func__)); put_u16(&req.length, 8); put_u32(&req.cmd, CMD_HDD_SIZE); return send_tf_packet(fd, &req); }
ssize_t send_cmd_turbo(int fd, int turbo_on) { struct tf_packet req; trace(2, fprintf(stderr, "%s\n", __func__)); put_u16(&req.length, 12); put_u32(&req.cmd, CMD_TURBO); put_u32(&req.data, turbo_on); return send_tf_packet(fd, &req); }
int send_cmd_hdd_del(libusb_device_handle* fd, char *path) { struct tf_packet req; __u16 packetSize; int pathLen = strlen(path) + 1; trace(3, printf("send_cmd_hdd_del\n")); if((PACKET_HEAD_SIZE + pathLen) >= MAXIMUM_PACKET_SIZE) { fprintf(stdout, "ERROR: Path is too long.\n"); return -1; } packetSize = PACKET_HEAD_SIZE + pathLen; packetSize = (packetSize + 1) & ~1; put_u16(&req.length, packetSize); put_u32(&req.cmd, CMD_HDD_DEL); strcpy((char *) req.data, path); return send_tf_packet(fd, &req); }
int send_cmd_hdd_file_send(libusb_device_handle* fd, __u8 dir, char *path) { struct tf_packet req; __u16 packetSize; int pathLen = strlen(path) + 1; trace(3, printf("send_cmd_hdd_file_send: %s \n",path)); if((PACKET_HEAD_SIZE + 1 + 2 + pathLen) >= MAXIMUM_PACKET_SIZE) { fprintf(stdout, "ERROR: Path is too long.\n"); return -1; } packetSize = PACKET_HEAD_SIZE + 1 + 2 + pathLen; packetSize = (packetSize + 1) & ~1; put_u16(&req.length, packetSize); put_u32(&req.cmd, CMD_HDD_FILE_SEND); req.data[0] = dir; put_u16(&req.data[1], (__u16) pathLen); strcpy((char *) &req.data[3], path); return send_tf_packet(fd, &req); }
ssize_t send_cmd_hdd_del(const int fd, const char *path) { struct tf_packet req; __u16 packetSize; int pathLen = strlen(path) + 1; trace(2, fprintf(stderr, "%s\n", __func__)); if((PACKET_HEAD_SIZE + pathLen) >= MAXIMUM_PACKET_SIZE) { fprintf(stderr, "ERROR: Path is too long.\n"); return -1; } packetSize = PACKET_HEAD_SIZE + pathLen; packetSize = (packetSize + 1) & ~1; put_u16(&req.length, packetSize); put_u32(&req.cmd, CMD_HDD_DEL); strcpy((char *) req.data, path); return send_tf_packet(fd, &req); }
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; }
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; }