Example #1
0
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;
}
Example #2
0
int main(int argc, char *argv[])
{
    struct usb_device_descriptor devDesc;
    int fd = -1;
    int r;

    /* Initialise timezone handling. */
    tzset();

    register_printf_function('W', quote_xml, quote_xml_arginfo);

    lockFd = open("/tmp/puppy", O_CREAT, S_IRUSR | S_IWUSR);
    if(lockFd < 0)
    {
        fprintf(stderr, "ERROR: Can not open lock file /tmp/puppy: %s\n",
                strerror(errno));
        return E_LOCK_FILE;
    }

    r = parseArgs(argc, argv);
    if(r != 0)
    {
        return E_INVALID_ARGS;
    }

    /* Create a lock, so that other instances of puppy can detect this one. */
    if(0 != flock(lockFd, LOCK_SH | LOCK_NB))
    {
        fprintf(stderr,
                "ERROR: Can not obtain shared lock on /tmp/puppy: %s\n",
                strerror(errno));
        return E_GLOBAL_LOCK;
    }

    trace(2, fprintf(stderr, "cmd %04x on %s\n", cmd, devPath));

    fd = open(devPath, O_RDWR);
    if(fd < 0)
    {
        fprintf(stderr, "ERROR: Can not open %s for read/write: %s\n",
                devPath, strerror(errno));
        return E_READ_DEVICE;
    }

    if(0 != flock(fd, LOCK_EX | LOCK_NB))
    {
        fprintf(stderr, "ERROR: Can not get exclusive lock on %s\n", devPath);
        close(fd);
        return E_DEVICE_LOCK;
    }

    r = read_device_descriptor(fd, &devDesc);
    if(r < 0)
    {
        close(fd);
        return E_READ_DEVICE;
    }

    if(!isToppy(&devDesc))
    {
        fprintf(stderr, "ERROR: Could not find a Topfield TF5000PVRt\n");
        close(fd);
        return E_NOT_TF5000PVR;
    }

    trace(1, fprintf(stderr, "Found a Topfield TF5000PVRt\n"));

    trace(2, fprintf(stderr, "USBDEVFS_RESET\n"));
    r = ioctl(fd, USBDEVFS_RESET, NULL);
    if(r < 0)
    {
        fprintf(stderr, "ERROR: Can not reset device: %s\n", strerror(errno));
        close(fd);
        return E_RESET_DEVICE;
    }

    {
        int interface = 0;

        trace(2, fprintf(stderr, "USBDEVFS_CLAIMINTERFACE\n"));
        r = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
        if(r < 0)
        {
            fprintf(stderr, "ERROR: Can not claim interface 0: %s\n",
                    strerror(errno));
            close(fd);
            return E_CLAIM_INTERFACE;
        }
    }

    {
        struct usbdevfs_setinterface interface0 = { 0, 0 };

        trace(2, fprintf(stderr, "USBDEVFS_SETNTERFACE\n"));
        r = ioctl(fd, USBDEVFS_SETINTERFACE, &interface0);
        if(r < 0)
        {
            fprintf(stderr, "ERROR: Can not set interface zero: %s\n",
                    strerror(errno));
            close(fd);
            return E_SET_INTERFACE;
        }
    }

    switch (cmd)
    {
        case CANCEL:
            r = do_cancel(fd);
            break;

        case CMD_RESET:
            r = do_cmd_reset(fd);
            break;

        case CMD_HDD_SIZE:
            r = do_hdd_size(fd);
            break;

        case CMD_HDD_DIR:
            r = do_hdd_dir(fd, arg1);
            break;

        case CMD_HDD_FILE_SEND:
            if(sendDirection == PUT)
            {
                r = do_hdd_file_put(fd, arg1, arg2);
            }
            else
            {
                r = do_hdd_file_get(fd, arg1, arg2);
            }
            break;

        case CMD_HDD_DEL:
            r = do_hdd_del(fd, arg1);
            break;

        case CMD_HDD_RENAME:
            r = do_hdd_rename(fd, arg1, arg2);
            break;

        case CMD_HDD_CREATE_DIR:
            r = do_hdd_mkdir(fd, arg1);
            break;

        case CMD_TURBO:
            r = do_cmd_turbo(fd, arg1);
            break;

        default:
            fprintf(stderr, "BUG: Command 0x%08x not implemented\n", cmd);
            r = -EINVAL;
    }

    {
        int interface = 0;

        ioctl(fd, USBDEVFS_RELEASEINTERFACE, &interface);
        close(fd);
    }
    return r;
}