Пример #1
0
/*
 *  delete file 
 */
int 
sx330z_delete_file(Camera *camera, GPContext *context, const char *filename)
{
 struct traveler_req req;
/* struct traveler_ack ack;*/
 uint8_t trxbuf[0x20];
 int ret, id;
 req.always1 = 1;
 req.requesttype = SX330Z_REQUEST_DELETE;					/* Delete */
 req.offset = 0x0;
 req.size = 0x000;
 req.timestamp = 0x0;							/* timestamp (doesn't matter)?*/
 req.data = 0;
 sprintf(req.filename, "%.8s", filename);
 sprintf(&req.filename[8], "jpg");					/* discard . */
 id = gp_context_progress_start(context, 2, "Deleting %s", filename);	/* start context */
 /* send delete request */
 sx330z_fill_req(trxbuf,&req);
 ret = gp_port_usb_msg_write(camera->port,
	USB_REQ_RESERVED, SX330Z_REQUEST_DELETE, 0, (char *)trxbuf, 0x20);
 if (ret != 0x20) return(GP_ERROR);						/* simple error handling */
 gp_context_progress_update(context, id, 1);				/* update context */
 /* read 16 Byte acknowledge packet */
 ret = gp_port_usb_msg_read(camera->port,
	USB_REQ_RESERVED, SX330Z_REQUEST_DELETE, 0, (char *)trxbuf, 0x10);
 if (ret != 0x10) return(GP_ERROR);
 
 gp_context_progress_stop(context, id);					/* stop context */
 return(GP_OK);
} /* sx330z delete file */
Пример #2
0
static int camera_get_file (Camera *camera, GPContext *context, int index,  
			    unsigned char **data, int *size) 
{
  unsigned char buffer[512];
  int nr_of_blocks = 0;
  int n,id,canceled=0;
  int picturebuffersize = 0;
  int offset = 0;  
  nr_of_blocks = pccam600_get_file(camera->port,context,index);
  if (nr_of_blocks < 0) 
    return GP_ERROR_FILE_NOT_FOUND;
  picturebuffersize = nr_of_blocks * 512;
  id = gp_context_progress_start(context,nr_of_blocks,_("Downloading file..."));
  *data= malloc(picturebuffersize+1);
  memset(*data,0,picturebuffersize+1);
  for (n = 0; n != nr_of_blocks; n++){
    pccam600_read_data(camera->port, buffer);
    memmove(&(*data)[offset],buffer,512);
    offset = offset + 512;
    gp_context_progress_update(context,id,n);
    if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL)
      {
	/* Keep reading data or else data will be invalid next time*/
	canceled = 1;
      }
  }
  *size = offset;
  gp_context_progress_stop(context,id);
  if (canceled) return GP_ERROR_CANCEL;
  return GP_OK;
}
Пример #3
0
/*
 * Getting picture off a logitech pocket digital
 */
static int
getpicture_logitech_pd(Camera *camera, GPContext *context, unsigned char **rd, const char *filename) {
    GPPort *port = camera->port;
    unsigned char  command[0x10] = { 0x11, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned char  retdata[0x8000];
    unsigned char *rawdata;
    int            ptc,pc,id;

    memcpy(command+3, filename, 11); /* the id of the image to transfer */

    CHECK_RESULT(ultrapocket_command(port, 1, command, 0x10));

    /* the first packet has the header in it, plus the start of the data */
    CHECK_RESULT(ultrapocket_command(port, 0, retdata, 0x8000));

    /* 640 x 480 =ish 10 * 0x8000 */
    ptc = 10;

    rawdata = malloc(0x8000 * ptc * sizeof(char));
    if (!rawdata) return (GP_ERROR_NO_MEMORY);

    /* show how far we've got on the current image */
    id = gp_context_progress_start(context, ptc-1, _("Downloading image..."));

    memcpy(rawdata, retdata, 0x8000 * sizeof(char));
    for (pc=1;pc<ptc;pc++) {
	int ret = ultrapocket_command(port, 0, retdata, 0x8000);
	if (ret < GP_OK) {
    	    gp_context_progress_stop(context, id);
	    free (rawdata);
	    return ret;
	}
	gp_context_progress_update(context, id, pc);
	memcpy(rawdata + (pc * 0x8000), retdata, 0x8000 * sizeof(char));
    }
    gp_context_progress_stop(context, id);

    *rd = rawdata;
    return GP_OK;
}
Пример #4
0
static int
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
                void *data, GPContext *context)
{
        CameraFile *file;
        CameraFileInfo info;
        KncStatus status;
        unsigned int i, id;
        Camera *camera = data;
        int result;
	KncCamRes cr;

        /*
         * We can't get the filename from the camera.
         * But we decide to call the images %6i.jpeg', with the image id as
         * parameter. Therefore, let's get the image ids.
         */
        CR (knc_get_status (camera->pl->c, &cr, &status), context);
	CCR (cr, context);

        id = gp_context_progress_start (context, status.pictures,
                                        _("Getting file list..."));
        for (i = 0; i < status.pictures; i++) {

                /* Get information */
                gp_file_new (&file);
                result = get_info (camera, i + 1, &info, file, context);
                if (result < 0) {
                        gp_file_unref (file);
                        return (result);
                }

                /*
                 * Append directly to the filesystem instead of to the list,
                 * because we have additional information.
                 */
                gp_filesystem_append (camera->fs, folder, info.file.name,
                                      context);
                gp_filesystem_set_info_noop (camera->fs, folder, info, context);
                gp_filesystem_set_file_noop (camera->fs, folder, file, context);
                gp_file_unref (file);

                gp_context_idle (context);
                gp_context_progress_update (context, id, i + 1);
                if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
                        return (GP_ERROR_CANCEL);
        }
        gp_context_progress_stop (context, id);

        return (GP_OK);
}
Пример #5
0
/*
 *	file list function 
 */
static int 
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
		void *data, GPContext *context)
{
	Camera *camera = data;
	CameraFileInfo info;
	int32_t tpages=0;
	int pcnt,ecnt;		/* pagecounter, entrycounter*/
	struct traveler_toc_page toc;
	int id;
 
	/* get number of TOC pages */
	CR (sx330z_get_toc_num_pages (camera, context, &tpages));
	/* Read the TOC pages */
	id = gp_context_progress_start (context, tpages, _("Getting "
			"information on %i files..."), tpages);
	for (pcnt = 0; pcnt < tpages; pcnt++) {
		CR (sx330z_get_toc_page (camera, context, &toc, pcnt));
		for (ecnt = 0; ecnt < toc.numEntries; ecnt++) {
			char fn[20];

			info.audio.fields = GP_FILE_INFO_NONE;
			info.preview.fields = GP_FILE_INFO_TYPE;
			strcpy (info.preview.type, GP_MIME_EXIF);
			info.file.fields = GP_FILE_INFO_SIZE |
					   GP_FILE_INFO_TYPE |
					   GP_FILE_INFO_PERMISSIONS;
			info.file.size = toc.entries[ecnt].size;
			info.file.permissions = GP_FILE_PERM_READ |
						GP_FILE_PERM_DELETE;
			strcpy (info.file.type,GP_MIME_JPEG); 
			sprintf (fn, "%.12s", toc.entries[ecnt].name);

			/*
			 * Append directly to the filesystem instead of to
			 * the list, because we have additional information.
			 */
			gp_filesystem_append (camera->fs, folder, fn, context);
			gp_filesystem_set_info_noop (camera->fs, folder, fn,
						     info, context);
		}
		gp_context_progress_update (context, id, pcnt);
		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
			return (GP_ERROR_CANCEL);
	}
	
	gp_context_progress_stop (context, id);

	return (GP_OK);
}
Пример #6
0
static int
serial_image_reader(Camera *camera,CameraFile *file,int nr,unsigned char ***imagebufs,int *sizes, GPContext *context) {
    int	picnum,curread,ret=0;
    GPPort *port = camera->port;
    unsigned int id;

    jd11_select_image(port,nr);
    *imagebufs = (unsigned char**)malloc(3*sizeof(char**));
    for (picnum=0;picnum<3;picnum++) {
	curread=0;
	sizes[picnum] = jd11_imgsize(port);
	(*imagebufs)[picnum]=(unsigned char*)malloc(sizes[picnum]+400);
	_send_cmd(port,0xfff1);
	id = gp_context_progress_start (context, sizes[picnum],
			_("Downloading data..."));
	while (curread<sizes[picnum]) {
	    int readsize = sizes[picnum]-curread;
	    if (readsize > 200) readsize = 200;
	    ret=getpacket(port,(*imagebufs)[picnum]+curread,readsize);
	    if (ret==0)
		break;
	    curread+=ret;
	    if (ret<200)
		break;
	    gp_context_progress_update (context, id, curread);
	    if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
		int j;
		/* What to do ... Just free the stuff we allocated for now. */
		for (j=0;j<picnum;j++)
		    free((*imagebufs)[picnum]);
		free(*imagebufs);
		return GP_ERROR_CANCEL;
	    }
	    _send_cmd(port,0xfff1);
	}
	gp_context_progress_stop (context, id);
    }
    return GP_OK;
}
Пример #7
0
static int
put_file_func (CameraFilesystem *fs, const char *folder,
	       CameraFile *file, void *data, GPContext *context)
{
	char path[2048];
	const char *name;
	int result;
#ifdef DEBUG
	unsigned int i, id;
#endif
	Camera *camera = (Camera*)data;

	gp_file_get_name (file, &name);

	result = _get_path (camera->port, folder, name, path, sizeof(path));
	if (result < GP_OK)
		return result;

	result = gp_file_save (file, path);
	if (result < 0)
		return (result);

#ifdef DEBUG
	id = gp_context_progress_start (context, 500., "Uploading file...");
	for (i = 0; i < 500; i++) {
		gp_context_progress_update (context, id, i + 1);
		gp_context_idle (context);
		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
			return (result);
		usleep (10);
	}
	gp_context_progress_stop (context, id);
#endif

	return (GP_OK);
}
Пример #8
0
/*
 *  get data 
 * could be  Image / Thumbnail 
 */
int 
sx330z_get_data(Camera *camera, GPContext *context, const char *filename,
   		 char **data, unsigned long int *size, int thumbnail)
{
 uint8_t *dptr;
 int pages, cnt, ret;
 struct traveler_req req;
 int found;
 int tocpages, tcnt, ecnt;
 struct traveler_toc_page toc;
 int id;/* progress ? */ 
 pages = 0;
 found = 0;
 memcpy(req.filename, filename, 12);
 
 if (thumbnail == SX_THUMBNAIL) 
 {
  if (camera->pl->usb_product == USB_PRODUCT_MD9700)
    pages = 7; /* first 28k only*/
   else  
    pages = 5; /* first 20k only */
  req.filename[0] = 'T';		/* 'T'humbnail indicator ?*/
  id = gp_context_progress_start(context, 0x1000 * pages, "Thumbnail %.4s _", &filename[4]);
 } else
 {
  /* I don't like this solution ... */
  ret = sx330z_get_toc_num_pages(camera, context, &tocpages);	/* number of toc pages */
  if (ret != GP_OK) return(ret);
  for (tcnt = 0;(tcnt < tocpages) && (!found);tcnt++)
  {
   ret = sx330z_get_toc_page(camera, context, &toc, tcnt);
   for (ecnt = 0;ecnt < toc.numEntries;ecnt++)
   {
    if (strncmp(toc.entries[ecnt].name, filename,8) == 0)
     {
      found = 1;
      *size = toc.entries[ecnt].size;
      break;
     }
   } /* */
  } /* load all toc pages */
  /*return(GP_ERROR);*/
  if (!found) return(GP_ERROR);
  if (((*size % 4096) != 0) || (*size == 0)) return(GP_ERROR);  /* sanity check */
  pages = *size / 0x1000;
  id = gp_context_progress_start(context, *size, "Picture %.4s _", &filename[4]);
 } /* real image */
  
 *size = 4096 * pages; 
 *data = malloc(*size);
 dptr = (uint8_t *)*data;
 /* load all parts */
 for (cnt = 0;cnt < pages;cnt++)
 {
  req.always1 = 1;
  req.requesttype = SX330Z_REQUEST_IMAGE;		/* Imagedata */
  req.offset = cnt * 0x1000;
  req.size = 0x1000;
  req.timestamp = 0x0 + cnt * 0x41;			/* timestamp (doesn't matter)?*/
  req.data = 0;
  gp_context_progress_update(context, id, (cnt + 1) * 0x1000);
  sx330z_read_block(camera,context,&req,dptr);  /* read data */
  dptr += 4096;
 }/* download imageparts */     
 gp_context_progress_stop(context,id);
 return(GP_OK);
} /* sx330z_get_data */
Пример #9
0
static void
on_ok_clicked (GtkButton *button, GtkamSave *save)
{
	guint i, count, j = 1;
	int result = -1;
	GtkWidget *s, *dialog;
	unsigned int id = 0;
	GtkamSaveData *data;
	gchar *progname, *command;
	GError *error = NULL;

	if (count_items (save) == 0) {
		if (!save->priv->err_shown) {
			
			dialog = gtkam_error_new (result, NULL,
					GTK_WIDGET (save), _("There is nothing to be saved."));
			gtk_widget_show (dialog);
		}

		return;
	}
			
	store_save_settings(save);
	gtk_widget_hide (GTK_WIDGET (save));

	count = g_slist_length (save->priv->data);
	if (count == 1)
		s = gtkam_cancel_new (_("Downloading file"));
	else
		s = gtkam_cancel_new (_("Downloading %i files"), count);
	gtk_window_set_transient_for (GTK_WINDOW (s), save->priv->main_window);
	gtk_widget_show (s);

	if (count > 1)
		id = gp_context_progress_start (
			GTKAM_CANCEL (s)->context->context, count,
			_("Downloading %i files..."), count);

	if (!save->priv->toggle_filename_camera->active)
		j = gtk_spin_button_get_value_as_int (
				GTK_SPIN_BUTTON (save->priv->spin_entry));
	
	for (i = 0; i < count; i++) {
		data = g_slist_nth_data (save->priv->data, i);

		/* Check for shutdown */
		if (!GTKAM_IS_SAVE (save))
			return;

		if (save->priv->toggle_normal &&
		    save->priv->toggle_normal->active)
			result = get_file (save, data->camera,
				  data->folder, data->name,
				  GP_FILE_TYPE_NORMAL, i + j,
				  GTKAM_CANCEL (s)->context);
		if (save->priv->toggle_preview &&
		    save->priv->toggle_preview->active &&
		    (!result < 0))
			result = get_file (save, data->camera,
				  data->folder, data->name,
				  GP_FILE_TYPE_PREVIEW, i + j,
				  GTKAM_CANCEL (s)->context);
		if (save->priv->toggle_raw &&
		    save->priv->toggle_raw->active &&
		    (!result < 0))
			result = get_file (save, data->camera,
				  data->folder, data->name, GP_FILE_TYPE_RAW,
				  i + j, GTKAM_CANCEL (s)->context);
		if (save->priv->toggle_audio &&
		    save->priv->toggle_audio->active &&
		    (!result < 0))
			result = get_file (save, data->camera,
				  data->folder, data->name, GP_FILE_TYPE_AUDIO,
				  i + j, GTKAM_CANCEL (s)->context);
		if (save->priv->toggle_exif &&
		    save->priv->toggle_exif->active &&
		    (!result < 0))
			result = get_file (save, data->camera,
				  data->folder, data->name, GP_FILE_TYPE_EXIF,
				  i + j, GTKAM_CANCEL (s)->context);

		if (result < 0)
		{
			if (count > 1)
				gp_context_progress_stop (GTKAM_CANCEL (s)->context->context, id);
			if (!save->priv->err_shown) {
				dialog = gtkam_error_new (result, GTKAM_CANCEL (s)->context,
						GTK_WIDGET (save), _("Problem getting '%s' "
						"from folder '%s'."),
						data->name, data->folder);
				gtk_widget_show (dialog);
				save->priv->err_shown = TRUE;
			}
	
			gtk_object_destroy (GTK_OBJECT (s));
			gtk_object_destroy (GTK_OBJECT (save));
			return;
		}
		
		if (count > 1)
			gp_context_progress_update (
				GTKAM_CANCEL (s)->context->context, id, i + 1);
		gp_context_idle (GTKAM_CANCEL (s)->context->context);
		if (gp_context_cancel (GTKAM_CANCEL (s)->context->context) ==
				GP_CONTEXT_FEEDBACK_CANCEL)
			break;
	}
	if (count > 1)
		gp_context_progress_stop (
				GTKAM_CANCEL (s)->context->context, id);
	
	gtk_object_destroy (GTK_OBJECT (s));

	/* If file(s) were saved and a program specified, load the program
   passing the filenames */
	if (result >= 0)
	{
		progname = gtk_entry_get_text (save->priv->program);

		if (progname && progname[0] != '\0') {
			command = g_strdup_printf ("%s%s", progname, save->priv->filelist->str);

			/* FIXME Report any arising errors */
			if (!g_spawn_command_line_async (command, &error)) {
				g_warning ("Error running command\n");
				g_error_free (error);
			}
			
			g_free (command);
			g_string_free (save->priv->filelist, TRUE);
		} 
	}
	
	gtk_object_destroy (GTK_OBJECT (save));
}
Пример #10
0
static int
file_list_func (CameraFilesystem *fs, const char *folder,
		CameraList *list, void *data, GPContext *context)
{
	Camera *camera = data;
	unsigned int i, filecount, id, size, type;
	CameraFile *file;
	CameraFileInfo info;
	unsigned char *buffer = NULL;
	int ret, n_img=0, n_avi=0, n_wav=0;
	char fn[100];

	CHECK (pccam300_get_filecount (camera->port, &filecount));

	id = gp_context_progress_start (context, filecount,
			_("Getting file list..."));
	
	for (i = 0; i < filecount; i++) {
		/* Get information */
		gp_file_new (&file);
	
		ret = pccam300_get_file (camera->port, context, i,
		                          &buffer, &size, &type);
		if (ret < GP_OK) {
			gp_file_free (file);
			return ret;
		}

		info.audio.fields = GP_FILE_INFO_NONE;
		info.preview.fields = GP_FILE_INFO_NONE;

		info.file.fields = GP_FILE_INFO_SIZE | GP_FILE_INFO_TYPE;
		info.file.size = size;

		switch (type) {
			case PCCAM300_MIME_JPEG:
				strcpy (info.file.type, GP_MIME_JPEG);
				sprintf (fn, "Image%03i.jpeg", n_img++);
				break;
			case PCCAM300_MIME_AVI:
				strcpy (info.file.type, GP_MIME_AVI);
				sprintf (fn, "Movie%03i.UNUSABLE", n_avi++);
				break;
			case PCCAM300_MIME_WAV:
				strcpy (info.file.type, GP_MIME_WAV);
				sprintf (fn, "Audio%03i.UNUSABLE", n_wav++);
				break;
			default:
				break;
		}

		if (file)
			gp_file_set_data_and_size (file, buffer, size);
		else
			free (buffer);
		
		/*
		 * Append directly to the filesystem instead of to the list,
		 * because we have additional information. 
		 * */
		gp_filesystem_append (camera->fs, folder, fn, context);
		gp_filesystem_set_info_noop (camera->fs, folder, fn, info, context);
		gp_filesystem_set_file_noop (camera->fs, folder, fn, GP_FILE_TYPE_NORMAL,
					file, context);
		gp_file_unref (file);

		gp_context_idle (context);
		gp_context_progress_update (context, id, i + 1);
		if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL)
			return (GP_ERROR_CANCEL);
	}
	gp_context_progress_stop (context, id);
	return GP_OK;
}
Пример #11
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;
}
Пример #12
0
/*
 * Upload an image to the camera
 */
static int
put_file_func (CameraFilesystem *fs, const char *folder, const char *name,
		CameraFileType type, CameraFile *file, 
		void *data, GPContext *context)
{
	Camera *camera = data;
	unsigned char	cmd[2], buf[DATA_BUFFER],ack,sum,state;
	const char *d;
	unsigned long int len, len_sent=0;
	unsigned int id;
	int ret,i;
	
	GP_DEBUG ("*** ENTER: put_file_func ***");

	/* Send function */
	cmd[0] = ESC;
	cmd[1] = UPLOADDATA;
	ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd)); 
	if (ret<GP_OK) 
		return ret;
	gp_file_get_data_and_size(file, &d, &len);
	id = gp_context_progress_start (context, len, _("Uploading image..."));
	for (i=0; i < ((len+DATA_BUFFER-1) / DATA_BUFFER); i++) {
		ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
		if (ret<GP_OK) {
			gp_context_progress_stop (context, id);
			return ret;
		}
		if (ack != ACK) {
			gp_context_progress_stop (context, id);
			gp_context_error(context, 
				_("Can't upload this image to the camera. "
				"An error has occurred."));
			return (GP_ERROR);
		}
		state = NEXTFRAME;
		ret = gp_port_write (camera->port, (char*)&state, STATE_LEN); 
		if (ret<GP_OK) {
			gp_context_progress_stop (context, id);
			return ret;
		}
		if ((len - len_sent) <= DATA_BUFFER) {
			/* Send the last datas */
			ret = gp_port_write (camera->port, (char*)&d[i*DATA_BUFFER],
				(len - len_sent));
			if (ret<GP_OK) {
				gp_context_progress_stop (context, id);
				return ret;
			}
			/* and complete with zeros */
			memset(buf,0,DATA_BUFFER);
			ret = gp_port_write (camera->port, (char*)buf, (DATA_BUFFER - 
				(len - len_sent)));
			if (ret<GP_OK) {
				gp_context_progress_stop (context, id);
				return ret;
			}
			/* Calculate the checksum */
			sum = k_calculate_checksum(
				(unsigned char *)&d[i*DATA_BUFFER],
				(len-len_sent));
			len_sent += (len - len_sent);
		}
		else {
			/* Just send the datas */
			ret = gp_port_write (camera->port, &d[i*DATA_BUFFER],
				DATA_BUFFER);
			if (ret<GP_OK) {
				gp_context_progress_stop (context, id);
				return ret;
			}
			len_sent += DATA_BUFFER;
			sum = k_calculate_checksum(
				(unsigned char *)&d[i*DATA_BUFFER],
				DATA_BUFFER);
		}
		ret = gp_port_write (camera->port, (char*)&sum, CSUM_LEN); 
		if (ret<GP_OK) {
			gp_context_progress_stop (context, id);
			return ret;
		}
		gp_context_progress_update (context, id, len_sent);
	}
	state = EOT;
	ret = gp_port_write (camera->port, (char*)&state, STATE_LEN); 
	if (ret<GP_OK) {
		gp_context_progress_stop (context, id);
		return ret;
	}
	ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
	if (ret<GP_OK) {
		gp_context_progress_stop (context, id);
		return ret;
	}
	if (ack != ACK) {
		gp_context_progress_stop (context, id);
		gp_context_error(context, _("Can't upload this image to the "
			"camera. An error has occurred."));
		return (GP_ERROR);
	}
	gp_context_progress_stop (context, id);
	return (GP_OK);
}
Пример #13
0
uint16_t
ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler)
{
	uint16_t ret;
	PTPUSBBulkContainer usbdata;
	unsigned char	*data;
	unsigned long	bytes_to_read, written, curread, oldsize;
	Camera		*camera = ((PTPData *)params->data)->camera;
	int usecontext, progressid = 0, tries = 0, res;
	GPContext *context = ((PTPData *)params->data)->context;

	gp_log (GP_LOG_DEBUG, "ptp2/ptp_usb_getdata", "reading data");
	PTP_CNT_INIT(usbdata);
	do {
		unsigned long len, rlen;

		ret = ptp_usb_getpacket(params, &usbdata, &rlen);
		if (ret!=PTP_RC_OK) {
			ret = PTP_ERROR_IO;
			break;
		}
		if (dtoh16(usbdata.type)!=PTP_USB_CONTAINER_DATA) {
			/* We might have got a response instead. On error for instance. */
			if (dtoh16(usbdata.type) == PTP_USB_CONTAINER_RESPONSE) {
				params->response_packet = malloc(dtoh32(usbdata.length));
				if (!params->response_packet) return PTP_RC_GeneralError;
				memcpy(params->response_packet,
				       (uint8_t *) &usbdata, dtoh32(usbdata.length));
				params->response_packet_size = dtoh32(usbdata.length);
				ret = PTP_RC_OK;
			} else {
				ret = PTP_ERROR_DATA_EXPECTED;
			}
			break;
		}
		if (dtoh16(usbdata.code)!=ptp->Code) {
			/* A creative Zen device breaks down here, by leaving out
			 * Code and Transaction ID */
			if (MTP_ZEN_BROKEN_HEADER(params)) {
				gp_log (GP_LOG_DEBUG, "ptp2/ptp_usb_getdata", "Read broken PTP header (Code is %04x vs %04x), compensating.",
					dtoh16(usbdata.code), ptp->Code
				);
				usbdata.code = dtoh16(ptp->Code);
				usbdata.trans_id = htod32(ptp->Transaction_ID);
			} else {
				gp_log (GP_LOG_ERROR, "ptp2/ptp_usb_getdata", "Read broken PTP header (Code is %04x vs %04x).",
					dtoh16(usbdata.code), ptp->Code
				);
				ret = PTP_ERROR_IO;
				break;
			}
		}
		if (usbdata.length == 0xffffffffU) {
			unsigned char	*data = malloc (PTP_USB_BULK_HS_MAX_PACKET_LEN_READ);
			if (!data) return PTP_RC_GeneralError;
			/* Copy first part of data to 'data' */
			handler->putfunc(
				params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, usbdata.payload.data,
				&written
			);
			/* stuff data directly to passed data handler */
			while (1) {
				unsigned long written;
				int result = gp_port_read (camera->port, (char*)data, PTP_USB_BULK_HS_MAX_PACKET_LEN_READ);
				if (result < 0) {
					free (data);
					return PTP_ERROR_IO;
				}
				handler->putfunc (params, handler->priv, result, data, &written);
				if (result < PTP_USB_BULK_HS_MAX_PACKET_LEN_READ) 
					break;
			}
			free (data);
			return PTP_RC_OK;
		}
		if (rlen > dtoh32(usbdata.length)) {
			/*
			 * Buffer the surplus response packet if it is >=
			 * PTP_USB_BULK_HDR_LEN
			 * (i.e. it is probably an entire package)
			 * else discard it as erroneous surplus data.
			 * This will even work if more than 2 packets appear
			 * in the same transaction, they will just be handled
			 * iteratively.
			 *
			 * Marcus observed stray bytes on iRiver devices;
			 * these are still discarded.
			 */
			unsigned int packlen = dtoh32(usbdata.length);
			unsigned int surplen = rlen - packlen;

			if (surplen >= PTP_USB_BULK_HDR_LEN) {
				params->response_packet = malloc(surplen);
				if (!params->response_packet) return PTP_RC_GeneralError;
				memcpy(params->response_packet,
				       (uint8_t *) &usbdata + packlen, surplen);
				params->response_packet_size = surplen;
			} else {
				gp_log (GP_LOG_DEBUG, "ptp2/ptp_usb_getdata", "read %ld bytes too much, expect problems!", rlen - dtoh32(usbdata.length));
			}
			rlen = packlen;
		}

		/* For most PTP devices rlen is 512 == sizeof(usbdata)
		 * here. For MTP devices splitting header and data it might
		 * be 12.
		 */
		/* Evaluate full data length. */
		len=dtoh32(usbdata.length)-PTP_USB_BULK_HDR_LEN;

		/* autodetect split header/data MTP devices */
		if (dtoh32(usbdata.length) > 12 && (rlen==12))
			params->split_header_data = 1;

		/* Copy first part of data to 'data' */
		handler->putfunc(
			params, handler->priv, rlen - PTP_USB_BULK_HDR_LEN, usbdata.payload.data,
			&written
		);
		/* Is that all of data? */
		if (len+PTP_USB_BULK_HDR_LEN<=rlen) break;

		/* If not read the rest of it. */
retry:
		oldsize = 0;
		data = malloc(READLEN);
		if (!data) return PTP_RC_GeneralError;
		bytes_to_read = len - (rlen - PTP_USB_BULK_HDR_LEN);
		usecontext = (bytes_to_read > CONTEXT_BLOCK_SIZE);
		ret = PTP_RC_OK;
		if (usecontext)
			progressid = gp_context_progress_start (context, (bytes_to_read/CONTEXT_BLOCK_SIZE), _("Downloading..."));
		curread = 0; res = 0;
		while (bytes_to_read > 0) {
			unsigned long toread = bytes_to_read;

			/* read in large blobs.
			 * if smaller than large blob, read all but the last short packet
			 * depending on EP packetsize.
			 */
			if (toread > READLEN)
				toread = READLEN;
			else if (toread > params->maxpacketsize)
				toread = toread - (toread % params->maxpacketsize);
			res = gp_port_read (camera->port, (char*)data, toread);
			if (res <= 0) {
				ret = PTP_ERROR_IO;
				break;
			}
			ret = handler->putfunc (params, handler->priv,
				res, data, &written
			);
			if (ret != PTP_RC_OK)
				break;
			if (written != res) {
				ret = PTP_ERROR_IO;
				break;
			}
			bytes_to_read -= res;
			curread += res;
			if (usecontext && (oldsize/CONTEXT_BLOCK_SIZE < curread/CONTEXT_BLOCK_SIZE))
				gp_context_progress_update (context, progressid, curread/CONTEXT_BLOCK_SIZE);
			if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) {
				ret = PTP_ERROR_CANCEL;
				break;
			}
			oldsize = curread;
		}
		free (data);
		if (usecontext)
			gp_context_progress_stop (context, progressid);
		if (res == GP_ERROR_IO_READ) {
			gp_log (GP_LOG_DEBUG, "ptp2/usbread", "Clearing halt on IN EP and retrying once.");
			gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_IN);
			/* retrying only makes sense if we did not read anything yet */
			if ((tries++ < 1) && (curread == 0))
				goto retry;
		}

		if ((ret!=PTP_RC_OK) && (ret!=PTP_ERROR_CANCEL)) {
			ret = PTP_ERROR_IO;
			break;
		}
	} while (0);

	if ((ret!=PTP_RC_OK) && (ret!=PTP_ERROR_CANCEL)) {
		gp_log (GP_LOG_DEBUG, "ptp2/usb_getdata",
		"request code 0x%04x getting data error 0x%04x",
			ptp->Code, ret);
	}
	return ret;
}
int
gp_abilities_list_load_dir (CameraAbilitiesList *list, const char *dir,
			    GPContext *context)
{
	CameraLibraryIdFunc id;
	CameraLibraryAbilitiesFunc ab;
	CameraText text;
	int ret, x, old_count, new_count;
	unsigned int i, p;
	const char *filename;
	CameraList *flist;
	int count;
	lt_dlhandle lh;

	CHECK_NULL (list && dir);

	gp_log (GP_LOG_DEBUG, "gphoto2-abilities-list",
		"Using ltdl to load camera libraries from '%s'...", dir);
	CHECK_RESULT (gp_list_new (&flist));
	ret = gp_list_reset (flist);
	if (ret < GP_OK) {
		gp_list_free (flist);
		return ret;
	}
	if (1) { /* a new block in which we can define a temporary variable */
		foreach_data_t foreach_data = { NULL, GP_OK };
		foreach_data.list = flist;
		lt_dlinit ();
		lt_dladdsearchdir (dir);
		ret = lt_dlforeachfile (dir, foreach_func, &foreach_data);
		lt_dlexit ();
		if (ret != 0) {
			gp_list_free (flist);
			gp_log (GP_LOG_ERROR, "gp-abilities-list", 
				"Internal error looking for camlibs (%d)", ret);
			gp_context_error (context,
					  _("Internal error looking for camlibs. "
					    "(path names too long?)"));
			return (foreach_data.result!=GP_OK)?foreach_data.result:GP_ERROR;
		}
	}
	count = gp_list_count (flist);
	if (count < GP_OK) {
		gp_list_free (flist);
		return ret;
	}
	gp_log (GP_LOG_DEBUG, "gp-abilities-list", "Found %i "
		"camera drivers.", count);
	lt_dlinit ();
	p = gp_context_progress_start (context, count,
		_("Loading camera drivers from '%s'..."), dir);
	for (i = 0; i < count; i++) {
		ret = gp_list_get_name (flist, i, &filename);
		if (ret < GP_OK) {
			gp_list_free (flist);
			return ret;
		}
		lh = lt_dlopenext (filename);
		if (!lh) {
			gp_log (GP_LOG_DEBUG, "gphoto2-abilities-list",
				"Failed to load '%s': %s.", filename,
				lt_dlerror ());
			continue;
		}

		/* camera_id */
		id = lt_dlsym (lh, "camera_id");
		if (!id) {
			gp_log (GP_LOG_DEBUG, "gphoto2-abilities-list",
				"Library '%s' does not seem to "
				"contain a camera_id function: %s",
				filename, lt_dlerror ());
			lt_dlclose (lh);
			continue;
		}

		/*
		 * Make sure the camera driver hasn't been
		 * loaded yet.
		 */
		if (id (&text) != GP_OK) {
			lt_dlclose (lh);
			continue;
		}
		if (gp_abilities_list_lookup_id (list, text.text) >= 0) {
			lt_dlclose (lh);
			continue;
		} 

		/* camera_abilities */
		ab = lt_dlsym (lh, "camera_abilities");
		if (!ab) {
			gp_log (GP_LOG_DEBUG, "gphoto2-abilities-list",
				"Library '%s' does not seem to "
				"contain a camera_abilities function: "
				"%s", filename, lt_dlerror ());
			lt_dlclose (lh);
			continue;
		}

		old_count = gp_abilities_list_count (list);
		if (old_count < 0) {
			lt_dlclose (lh);
			continue;
		}

		if (ab (list) != GP_OK) {
			lt_dlclose (lh);
			continue;
		}

		lt_dlclose (lh);

		new_count = gp_abilities_list_count (list);
		if (new_count < 0)
			continue;

		/* Copy in the core-specific information */
		for (x = old_count; x < new_count; x++) {
			strcpy (list->abilities[x].id, text.text);
			strcpy (list->abilities[x].library, filename);
		}

		gp_context_progress_update (context, p, i);
		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
			lt_dlexit ();
			gp_list_free (flist);
			return (GP_ERROR_CANCEL); 
		}
	}
	gp_context_progress_stop (context, p);
	lt_dlexit ();
	gp_list_free (flist);

	return (GP_OK);
}
Пример #15
0
/* Download a raw Bayer image from the camera and return it in a malloced
buffer */
static uint8_t *
Dimera_Get_Full_Image (int picnum, long *size, int *width, int *height,
			Camera *camera, GPContext *context)
{
	static struct mesa_image_arg	ia;
	int32_t				r;
	uint8_t			*b, *rbuffer = NULL;
	int				hires, s, retry;
	unsigned int id;

	*size = 0;
	*width = 0;
	*height = 0;

	if ( picnum != RAM_IMAGE_NUM )
	{
		GP_DEBUG("Getting Image Info");
		if ( (r = mesa_read_image_info( camera->port, picnum, NULL )) < 0 )
		{
			ERROR("Can't get Image Info");
			gp_context_error (context, _("Problem getting image information"));
			return NULL;
		}
		if ( r )
		{
			hires = FALSE;
			*height = 240;
			*width = 320;
		} else {
			hires = TRUE;
			*height = 480;
			*width = 640;
		}

		GP_DEBUG("Loading Image");
		if ( mesa_load_image( camera->port, picnum ) != GP_OK )
		{
			ERROR("Image Load failed");
			gp_context_error (context, _("Problem reading image from flash"));
			return NULL;
		}

	} else {
			/* load the snapped image */
		hires = TRUE;
		*height = 480;
		*width = 640;
	}

	*size = *height * *width;	/* 8 bits per pixel in raw CCD format */

	GP_DEBUG("Downloading Image");

	rbuffer = (uint8_t *)malloc( *size );
	if ( rbuffer == NULL )
	{
		gp_context_error (context, _("Out of memory"));
		return NULL;
	}

	ia.start = 28;
	ia.send = 4;
	ia.skip = 0;
	ia.repeat = ( hires ? 160 : 80 );
	ia.row_cnt = 40;
	ia.inc1 = 1;
	ia.inc2 = 128;
	ia.inc3 = ia.inc4 = 0;

	/* due to reports of mesa_read_image not working for some cameras */
	/* this is changed to use mesa_read_row */
#if 0
	id = gp_context_progress_start (context, *height + 4,
					_("Downloading image..."));
	for ( ia.row = 4, b = rbuffer; ia.row < (height + 4) ;
			ia.row += ia.row_cnt, b += s )
	{
		GP_DEBUG("Downloading Image");
		for ( retry = 10;; )
		{

			s = mesa_read_image( camera->port, b, &ia );
			if( s > 0)
				break;

			if ( (s == GP_ERROR_TIMEOUT || s == GP_ERROR_CORRUPTED_DATA) && --retry > 0)
			{
				GP_DEBUG( "Dimera_Get_Full_Image: retrans"); 
				continue;
			}
			GP_DEBUG(
				"Dimera_Get_Full_Image: read error %d (retry %d)",s,retry);
				/* retry count exceeded, or other error */
			free( rbuffer );
			*size = 0;
			gp_context_error (context, _("Problem downloading image"));
			return NULL;
		}
		gp_context_progress_update (context, id, ia.row);
		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
		{
			free( rbuffer );
			*size = 0;
			gp_context_error (context, _("User canceled download"));
			return NULL;
		}
	}
#else
	id = gp_context_progress_start (context, *height + 4,
					_("Downloading image..."));
	for ( ia.row = 4, b = rbuffer; ia.row < (*height + 4) ;
			ia.row++, b += s )
	{
		GP_DEBUG("Downloading Image");
		for ( retry = 10;; )
		{

			s = mesa_read_row( camera->port, b, &ia );
			if( s > 0)
				break;

			if ( (s == GP_ERROR_TIMEOUT || s == GP_ERROR_CORRUPTED_DATA) && --retry > 0)
			{
				GP_DEBUG("Dimera_Get_Full_Image: retrans"); 
				continue;
			}
			GP_DEBUG(
				"Dimera_Get_Full_Image: read error %d (retry %d)",s,retry);
				/* retry count exceeded, or other error */
			free( rbuffer );
			*size = 0;
			gp_context_error (context, _("Problem downloading image"));
			return NULL;
		}
		gp_context_progress_update (context, id, ia.row);
		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL)
		{
			free( rbuffer );
			*size = 0;
			return NULL;
		}
	}
	gp_context_progress_stop (context, id);
#endif

	return (rbuffer);
}
Пример #16
0
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
	       CameraFileType type, CameraFile *file, void *user_data,
	       GPContext *context)
{
	Camera *camera = user_data;
	int result;
	int havefirst = 0;
	unsigned char buffer[SDSC_BLOCKSIZE], first[SDSC_BLOCKSIZE];
	long int size, curread;
	unsigned int pid;

	if (type != GP_FILE_TYPE_NORMAL)
		return (GP_ERROR_NOT_SUPPORTED);

	/* Seek the header of our file */
	while (1) {
		CHECK_RESULT (SDSC_send (camera->port, SDSC_NEXT));
		CHECK_RESULT (SDSC_send (camera->port, SDSC_START));
		CHECK_RESULT (SDSC_receive (camera->port, buffer, SDSC_INFOSIZE));
		if (!strcmp(buffer,filename))
		    break;
		if (is_null(buffer)) { /* skipped to the end of the camera? */
		    /* Since we start at a random position, we wrap around. */
		    continue;
	        }
		/* We are at the first item again, so break. */
		if (havefirst && !strcmp(first,buffer))
			return GP_ERROR_BAD_PARAMETERS;
		if (!havefirst) {
			havefirst = 1;
			strcpy(first,buffer);
		}
	}
	/* The buffer header has
	 * filename (8.3 DOS format and \0)
	 * filesize (as ascii number) and \0
	 */
	/* Extract the size of the file */
	sscanf(buffer+12,"%ld",&size);
	/* Put the camera into image mode */
	CHECK_RESULT (SDSC_send (camera->port, SDSC_BINARY));
	CHECK_RESULT (SDSC_send (camera->port, SDSC_START));

	pid = gp_context_progress_start(context,size,_("Downloading image..."));

	curread = 0;
	/* Read data */
	while (1) {
		/* Read data and check for EOF */
		result = SDSC_receive (camera->port, buffer, SDSC_BLOCKSIZE);
		if (result == SDSC_ERROR_EOF)
			break;
		if (result < 0)
			return result;
		gp_file_append(file,buffer,SDSC_BLOCKSIZE);
		curread += SDSC_BLOCKSIZE;
	        gp_context_progress_update(context, pid, curread);
		if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL)
		    return GP_ERROR_CANCEL;
		CHECK_RESULT (SDSC_send (camera->port, SDSC_BINARY));
	}
	gp_context_progress_stop(context, pid);
	CHECK_RESULT (gp_file_set_mime_type (file, GP_MIME_JPEG));
	return (GP_OK);
}
Пример #17
0
static int
get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
	       CameraFileType type, CameraFile *file, void *user_data,
	       GPContext *context)
{
        char path[1024];
	int result = GP_OK;
	struct stat stbuf;
	int fd, id;
	unsigned int curread, toread;
	unsigned char *buf;
#ifdef HAVE_LIBEXIF
	ExifData *data;
	unsigned int buf_len;
#endif /* HAVE_LIBEXIF */
	Camera *camera = (Camera*)user_data;

	result = _get_path (camera->port, folder, filename, path, sizeof(path));
	gp_log (GP_LOG_DEBUG, "directory/get_file_func", "%s %s",folder,filename);
	if (result < GP_OK)
		return result;
	gp_log (GP_LOG_DEBUG, "directory/get_file_func", "->%s",path);
	

	switch (type) {
	case GP_FILE_TYPE_NORMAL:
#ifdef DEBUG
	case GP_FILE_TYPE_PREVIEW:
#endif
		fd = open (path,O_RDONLY);
		if (fd == -1)
			return GP_ERROR_IO_READ;
		break;
#ifdef HAVE_LIBEXIF
	case GP_FILE_TYPE_EXIF:
		data = exif_data_new_from_file (path);
		if (!data) {
			gp_context_error (context, _("Could not open '%s'."),
					  path);
			return (GP_ERROR);
		}
		exif_data_save_data (data, &buf, &buf_len);
		exif_data_unref (data);
		gp_file_set_data_and_size (file, buf, buf_len);
		return (GP_OK);
#endif /* HAVE_LIBEXIF */
	default:
		return (GP_ERROR_NOT_SUPPORTED);
	}

	if (-1 == fstat(fd,&stbuf)) {
		close (fd);
		return GP_ERROR_IO_READ;
	}
#define BLOCKSIZE 65536
	/* do it in 64kb blocks */
	buf = malloc(BLOCKSIZE);
	if (!buf) {
		close (fd);
		return GP_ERROR_NO_MEMORY;
	}

	curread = 0;
	id = gp_context_progress_start (context, (1.0*stbuf.st_size/BLOCKSIZE), _("Getting file..."));
	GP_DEBUG ("Progress id: %i", id);
	result = GP_OK;
	while (curread < stbuf.st_size) {
		int ret;

		toread = stbuf.st_size-curread;
		if (toread>BLOCKSIZE) toread = BLOCKSIZE;
		ret = read(fd,buf,toread);
		if (ret == -1) {
			result = GP_ERROR_IO_READ;
			break;
		}
		curread += ret;
		gp_file_append (file, buf, ret);
		gp_context_progress_update (context, id, (1.0*curread/BLOCKSIZE));
		gp_context_idle (context);
		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
			result = GP_ERROR_CANCEL;
			break;
		}
#if 0
		/* We could take 2 seconds to download this image. everytime. */
		/* But actually this driver is used in production by some frontends,
		 * so do not delay at all
		 */
		usleep(2000000/(stbuf.st_size/BLOCKSIZE));
#endif
	}
	gp_context_progress_stop (context, id);
	free (buf);
	close (fd);
	return (GP_OK);
}
Пример #18
0
static int
folder_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
		  void *data, GPContext *context)
{
	gp_system_dir dir;
	gp_system_dirent de;
	char buf[1024], f[1024];
	unsigned int id, n;
	struct stat st;
	Camera *camera = (Camera*)data;

	if (camera->port->type == GP_PORT_DISK) {
		char		*path;
		GPPortInfo	info;
		int		ret;

		ret = gp_port_get_info (camera->port, &info);
		if (ret < GP_OK)
			return ret;
		path = strchr (info.path,':');
		if (!path) path = info.path; else path++;

		snprintf (f, sizeof(f), "%s/%s/", path, folder);
		gp_log (GP_LOG_DEBUG, "directory/folder_list_func", "%s", f);
		/* UNIX / is empty, or we recurse through the whole fs */
		if (	(!strcmp(path, "") || !strcmp(path, "/")) &&
			!strcmp(folder,"/")
		)
			return GP_OK;
	} else {
		/* old style access */
		/* Make sure we have 1 delimiter */
		if (folder[strlen(folder)-1] != '/') {
			snprintf (f, sizeof(f), "%s%c", folder, '/');
		} else {
			strncpy (f, folder, sizeof(f));
		}
	}
	dir = gp_system_opendir ((char*) f);
	if (!dir)
		return GP_ERROR;
	/* Count the files */
	n = 0;
	while (gp_system_readdir (dir))
		n++;
	gp_system_closedir (dir);

	dir = gp_system_opendir (f);
	if (!dir)
		return GP_ERROR;
	id = gp_context_progress_start (context, n, _("Listing folders in '%s'..."), folder);
	n = 0;
	while ((de = gp_system_readdir (dir))) {
		const char * filename = NULL;

		/* Give some feedback */
		gp_context_progress_update (context, id, n + 1);
		gp_context_idle (context);
		if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
			gp_system_closedir (dir);
			return GP_ERROR_CANCEL;
		}
		filename = gp_system_filename (de);
		if (*filename != '.') {
			snprintf (buf, sizeof(buf), "%s%s", f, filename);
			
			/* lstat ... do not follow symlinks */
			if (lstat (buf, &st) != 0) {
				gp_context_error (context, _("Could not get information about '%s' (%m)."), buf);
				return GP_ERROR;
			}
			if (S_ISDIR (st.st_mode)) {
				gp_list_append(list,	filename,	NULL);
			}
		}
		n++;
	}
	gp_system_closedir (dir);
	gp_context_progress_stop (context, id);
	return (GP_OK);
}
Пример #19
0
/* we have to determine from the header what the RAW image is, QVGA or VGA */
static int
getpicture_generic(Camera *camera, GPContext *context, unsigned char **rd,int *retwidth, int *retheight, int *retimgstart, const char *filename) {
    GPPort *port = camera->port;
    unsigned char  command[0x10] = { 0x11, 0x01, 0x00, 0x49, 0x4d, 0x47, 0,0,0,0, 0x2e, 0x52, 0x41, 0x57, 0x00, 0x00 };
    unsigned char  retdata[0x1000];
    unsigned char  header[42];
    unsigned char *rawdata;
    int            width, height, imgstart;
    smal_img_type  styp;
    int            ptc,pc,id;

    memcpy(command+6, filename+3, 4); /* the id of the image to transfer */

    CHECK_RESULT(ultrapocket_command(port, 1, command, 0x10));

    /* the first packet has the header in it, plus the start of the data */
    CHECK_RESULT(ultrapocket_command(port, 0, retdata, 0x1000));
    memcpy(header, retdata, 41);
    styp = header[3];

    switch (styp) {
     case TYPE_QVGA:
	/* 24 packets, including one already got */
	ptc = 24;
	width = 320;
	height = 240;
	imgstart = 0x29;
	break;
     case TYPE_VGA:
	/* 80 including one already got. */
	ptc = 80;
	width = 640;
	height = 480;
	imgstart = 0x29;
	break;
     case TYPE_QVGA_BH:
	ptc = 24;
	width = 320;
	height = 240;
	imgstart = 0x100;
	break;
     case TYPE_VGA_BH:
	ptc = 80;
	width = 640;
	height = 480;
	imgstart = 0x100;
	break;
     default:
	return GP_ERROR;
   }
    rawdata = malloc(0x1000 * ptc * sizeof(char));
    if (!rawdata) return (GP_ERROR_NO_MEMORY);

    /* show how far we've got on the current image */
    id = gp_context_progress_start(context, ptc-1, _("Downloading image..."));

    memcpy(rawdata, retdata, 0x1000 * sizeof(char));
    for (pc=1;pc<ptc;pc++) {
	int ret = ultrapocket_command(port, 0, retdata, 0x1000);
	if (ret < GP_OK) {
	     free (rawdata);
	     gp_context_progress_stop(context, id);
	     return ret;
	}
	gp_context_progress_update(context, id, pc);
	memcpy(rawdata + (pc * 0x1000), retdata, 0x1000 * sizeof(char));
    }
    gp_context_progress_stop(context, id);

    *retwidth = width;
    *retheight = height;
    *retimgstart = imgstart;

    *rd = rawdata;
    return GP_OK;
}
Пример #20
0
static int 
l_receive (GPPort *p, GPContext *context,
	   unsigned char **rb, unsigned int *rbs,
	   unsigned int timeout)
{
	unsigned char c, d, progress = 0;
	int error_flag;
	unsigned int i, j, rbs_internal, id = 0;
	unsigned char checksum;
	int result;
	KCommand command;

	CHECK_NULL (p && rb && rbs);

	for (i = 0; ; ) {
		CHECK (gp_port_set_timeout (p, timeout));
		CHECK (gp_port_read (p, &c, 1));
		CHECK (gp_port_set_timeout (p, DEFAULT_TIMEOUT));
		switch (c) {
		case ENQ:

			/* ENQ received. We can proceed. */
			break;

		case ACK:

			/* ACK received. We'll try again at most ten times. */
			if (i == 9) {

				/*
				 * The camera hangs! Although it could be
				 * that the camera accepts one of the
				 * commands
				 *  - KONICA_CANCEL,
				 *  - KONICA_GET_IO_CAPABILITY, and
				 *  - KONICA_SET_IO_CAPABILITY,
				 * we can not get the camera back to working
				 * correctly.
				 */
				return (GP_ERROR_CORRUPTED_DATA);

			}
			i++;
			break;
		default:
			/*
			 * We'll dump this data until we get ENQ (then, we'll
			 * proceed) or nothing any more (then, we'll report
			 * error).
			 */
			for (;;) {
				CHECK (gp_port_read (p, &c, 1));
				if (c == ENQ)
					break;
			}
			break;
		}
		if (c == ENQ)
			break;
	}

	/* Start progress */
	if (*rbs > 1000) {
		id = gp_context_progress_start (context, *rbs,
						_("Downloading..."));
		progress = 1;
	}

	/* Write ACK. */
	CHECK (gp_port_write (p, "\6", 1));
	for (*rbs = 0; ; ) {
		for (j = 0; ; j++) {
			CHECK (gp_port_read (p, &c, 1));
			switch (c) {
			case STX:

				/* STX received. We can proceed. */
				break;

			default:

				/* We'll dump this data and try again. */
				continue;

			}

			/*
			 * Read 2 bytes for size (low order byte, high order
			 * byte) plus ESC quotes.
			 */
			CHECK (l_esc_read (p, &c));
			checksum = c;
			CHECK (l_esc_read (p, &d));
			checksum += d;
			rbs_internal = (d << 8) | c;
			if (*rbs == 0)
				*rb = malloc (rbs_internal * sizeof (char));
			else
				*rb = realloc (*rb,
					sizeof (char) * (*rbs + rbs_internal));

			/* Read 'rbs_internal' bytes data plus ESC quotes. */
			error_flag = 0;
{
unsigned int read = 0, r = 0;
while (read < rbs_internal) {

	/*
	 * Read the specified amount of bytes. We will probably read more
	 * because some bytes will be quoted.
	 */
	GP_DEBUG ("Reading %i bytes (%i of %i already read)...", 
		  rbs_internal - read, read, rbs_internal);
	result = gp_port_read (p, &((*rb)[*rbs + read]),
			       rbs_internal - read);
	if (result < 0) {
		error_flag = 1;
		break;
	}
	r = rbs_internal - read;

	/* Unescape the data we just read */
	for (i = read; i < read + r; i++) {
		unsigned char *c = &(*rb)[*rbs + i];

		 /* The HP PhotoSmart does not escape every special code, only
		  * some and it gets confused if we do this checks. By relaxing
		  * these, it now downloads images etc.
		  */
#ifndef LESSER_ESCAPES
	        if ((*c == STX) || (*c == ETX) || (*c == ENQ ) ||
		    (*c == ACK) || (*c == XOFF) || (*c == XON) ||
		    (*c == NACK) || (*c == ETB)) {
#else /* LESSER_ESCAPES */
	        if ((*c == STX) ||  (*c == XOFF) || (*c == XON)) {
#endif /* LESSER_ESCAPES */
			GP_DEBUG ("Wrong ESC masking!");
			error_flag = 1;
			break;
		} else if (*c == ESC) {
			if (i == read + r - 1) {
				/* ESC is last char of packet */
				CHECK (gp_port_read (p, c, 1));
			} else {
				memmove (c, c + 1, read + r - i - 1);
				r--;
			}
			*c = ~*c & 0xff;
			if ((*c != STX ) && (*c != ETX ) && (*c != ENQ) &&
			    (*c != ACK ) && (*c != XOFF) && (*c != XON) &&
			    (*c != NACK) && (*c != ETB ) && (*c != ESC)) {
				GP_DEBUG ("Wrong ESC masking!");
				error_flag = 1;
				break;
			}
		}
		checksum += (*rb)[*rbs + i];
	}
	if (error_flag)
		break;
	read += r;
}}
			if (!error_flag) {
				CHECK (gp_port_read (p, &d, 1));
				switch (d) {
				case ETX:

					/*
					 * ETX received. This is the last
					 * packet.
					 */
					GP_DEBUG ("Last packet.");
					break;

				case ETB:

					/*
					 * ETB received. There are more
					 * packets to come.
					 */
					GP_DEBUG ("More packets coming.");
					break;

				default:

					/*
					 * We get more bytes than expected.
					 * Nothing serious, as we will simply
					 * dump all bytes until we receive
					 * ETX or ETB. Later, we'll read the
					 * checksum with ESC quotes and
					 * reject the packet.
					 */
					while ((d != ETX) && (d != ETB)) {
						CHECK (gp_port_read (p,
								     &d, 1));
					}
					error_flag = 1;
					break;
				}
			}
			checksum += d;

			/* Read 1 byte for checksum plus ESC quotes. */
			CHECK (l_esc_read (p, &c));
			if ((c == checksum) && (!error_flag)) {
				*rbs += rbs_internal;

				/* Write ACK. */
				CHECK (gp_port_write (p, "\6", 1));
				break;

			} else {

				/*
				 * Checksum wrong or transmission error. The
				 * camera will send us the data at the most
				 * three times.
				 */
				GP_DEBUG ("Checksum wrong: expected %i, "
					  "got %i.", c, checksum);
				if (j == 2)
					return (GP_ERROR_CORRUPTED_DATA);

				/* Write NACK. */
				c = NACK;
				CHECK (gp_port_write (p, &c, 1));
				continue;
			}
		}
		CHECK (gp_port_read (p, &c, 1));
		switch (c) {
			case EOT:

				/* EOT received. We can proceed. */
				break;

			default:

				/* Should not happen. */
				return (GP_ERROR_CORRUPTED_DATA);
		}
		/*
		 * Depending on d, we will either continue to receive data or
		 * stop.
		 * 
		 *  - ETX:  We are all done.
		 *  - ETB:  We expect more data.
		 *  - else: Should not happen.
		 */
		switch (d) {
		case ETX:

			/* We are all done. */
			if (progress)
				gp_context_progress_stop (context, id);
			return (GP_OK);

		case ETB:

			/* We expect more data. Read ENQ. */
			CHECK (gp_port_read (p, &c, 1));
			switch (c) {
			case ENQ:

				/* ENQ received. We can proceed. */
				break;

			default:

				/* Should not happen. */
				return (GP_ERROR_CORRUPTED_DATA);
			}

			if (gp_context_cancel (context) ==
						GP_CONTEXT_FEEDBACK_CANCEL) {
				GP_DEBUG ("Trying to cancel operation...");
				CHECK (k_cancel (p, context, &command));
				GP_DEBUG ("Operation 0x%x cancelled.",
					  command);
				return (GP_ERROR_CANCEL);
			}

			/* Write ACK. */
			CHECK (gp_port_write (p, "\6", 1));
			break;

		default:

			/* Should not happen. */
			return (GP_ERROR_CORRUPTED_DATA);
		}
		if (progress)
			gp_context_progress_update (context, id, *rbs);
	}
}

int 
l_send_receive (
	GPPort *p, GPContext *c,
	unsigned char *send_buffer, unsigned int send_buffer_size, 
	unsigned char **receive_buffer, unsigned int *receive_buffer_size,
	unsigned int timeout,
	unsigned char **image_buffer, unsigned int *image_buffer_size)
{
	if (!timeout)
		timeout = DEFAULT_TIMEOUT;

	/* Send data. */
	CHECK (l_send (p, c, send_buffer, send_buffer_size));

        /* Receive data. */
	if (image_buffer_size)
		*receive_buffer_size = *image_buffer_size;
	CHECK (l_receive (p, c, receive_buffer, receive_buffer_size,
			  timeout));

	/* Check if we've received the control data. */
	if ((*receive_buffer_size > 1) &&
	    (((*receive_buffer)[0] == send_buffer[0]) &&
	     ((*receive_buffer)[1] == send_buffer[1])))
	    return (GP_OK);

	/* We didn't receive control data yet. */
	*image_buffer = *receive_buffer; 
	*image_buffer_size = *receive_buffer_size;
	*receive_buffer = NULL;
	
	/* Receive control data. */
	CHECK (l_receive (p, c, receive_buffer, receive_buffer_size,
			  DEFAULT_TIMEOUT));

	/* Sanity check: Did we receive the right control data? */
	if (((*receive_buffer)[0] != send_buffer[0]) ||
	    ((*receive_buffer)[1] != send_buffer[1]))
		return (GP_ERROR_CORRUPTED_DATA);
	
	return (GP_OK);
}
Пример #21
0
uint16_t
ptp_usb_senddata (PTPParams* params, PTPContainer* ptp,
		  uint64_t size, PTPDataHandler *handler
) {
	uint16_t ret = PTP_RC_OK;
	int res, wlen, datawlen;
	PTPUSBBulkContainer usbdata;
	unsigned long bytes_left_to_transfer, written;
	Camera *camera = ((PTPData *)params->data)->camera;
	unsigned char *bytes;
	int progressid = 0;
	int usecontext = (size > CONTEXT_BLOCK_SIZE);
	GPContext *context = ((PTPData *)params->data)->context;

	/* build appropriate USB container */
	usbdata.length	= htod32(PTP_USB_BULK_HDR_LEN+size);
	usbdata.type	= htod16(PTP_USB_CONTAINER_DATA);
	usbdata.code	= htod16(ptp->Code);
	usbdata.trans_id= htod32(ptp->Transaction_ID);

	if (params->split_header_data) {
		datawlen = 0;
		wlen = PTP_USB_BULK_HDR_LEN;
	} else {
		unsigned long gotlen;
		/* For all camera devices. */
		datawlen = (size<PTP_USB_BULK_PAYLOAD_LEN_WRITE)?size:PTP_USB_BULK_PAYLOAD_LEN_WRITE;
		wlen = PTP_USB_BULK_HDR_LEN + datawlen;
		ret = handler->getfunc(params, handler->priv, datawlen, usbdata.payload.data, &gotlen);
		if (ret != PTP_RC_OK)
			return ret;
		if (gotlen != datawlen)
			return PTP_RC_GeneralError;
	}
	res = gp_port_write (camera->port, (char*)&usbdata, wlen);
	if (res != wlen) {
		gp_log (GP_LOG_DEBUG, "ptp2/usb_senddata",
		"request code 0x%04x sending data error 0x%04x",
			ptp->Code,ret);
		return PTP_ERROR_IO;
	}
	if (size <= datawlen) { /* nothing more to do */
		written = wlen;
		goto finalize;
	}
	if (usecontext)
		progressid = gp_context_progress_start (context, (size/CONTEXT_BLOCK_SIZE), _("Uploading..."));
	bytes = malloc (4096);
	if (!bytes)
		return PTP_RC_GeneralError;
	/* if everything OK send the rest */
	bytes_left_to_transfer = size-datawlen;
	ret = PTP_RC_OK;
	written = 0;
	while(bytes_left_to_transfer > 0) {
		unsigned long readlen, toread, oldwritten = written;
		int res;

		toread = 4096;
		if (toread > bytes_left_to_transfer)
			toread = bytes_left_to_transfer;
		ret = handler->getfunc (params, handler->priv, toread, bytes, &readlen);
		if (ret != PTP_RC_OK)
			break;
		res = gp_port_write (camera->port, (char*)bytes, readlen);
		if (res < 0) {
			ret = PTP_ERROR_IO;
			break;
		}
		bytes_left_to_transfer -= res;
		written += res;
		if (usecontext && (oldwritten/CONTEXT_BLOCK_SIZE < written/CONTEXT_BLOCK_SIZE))
			gp_context_progress_update (context, progressid, written/CONTEXT_BLOCK_SIZE);
#if 0 /* Does not work this way... Hmm. */
		if (gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) {
			ret = ptp_usb_control_cancel_request (params,ptp->Transaction_ID);
			if (ret == PTP_RC_OK)
				ret = PTP_ERROR_CANCEL;
			break;
		}
#endif
	}
	if (usecontext)
		gp_context_progress_stop (context, progressid);
	free (bytes);
finalize:
	if ((ret == PTP_RC_OK) && ((written % params->maxpacketsize) == 0))
		gp_port_write (camera->port, "x", 0);
	if ((ret!=PTP_RC_OK) && (ret!=PTP_ERROR_CANCEL))
		ret = PTP_ERROR_IO;
	return ret;
}
Пример #22
0
/*
 * Get data from the camera
 * type = GP_FILE_TYPE_NORMAL, GP_FILE_TYPE_PREVIEW or GP_FILE_TYPE_EXIF
 */
static int
k_getdata (int image_no, int type, unsigned int len, void *data, 
		unsigned char *d, GPContext *context)
{
	Camera *camera = data;
	unsigned char ack,state, cmd[7], buf[DATA_BUFFER], *buffer=d;
	unsigned int id=0, bytes_read=0, i;
	int ret;

	cmd[0] = ESC;
	cmd[1] = GETIMAGE_CMD1;
	if (type != GP_FILE_TYPE_NORMAL)
		cmd[1] = GETTHUMBNAIL_CMD1;
	cmd[2] = IMAGE_CMD2;
	cmd[3] = 0x30 + ((image_no/1000)%10);
	cmd[4] = 0x30 + ((image_no/100 )%10);
	cmd[5] = 0x30 + ((image_no/10  )%10);
	cmd[6] = 0x30 + ( image_no      %10);

	ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
	if (ret<GP_OK) return ret;
	ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
	if (ret < GP_OK) return ret;
	if (ack == NACK) {
		gp_context_error(context, _("This preview doesn't exist."));
		return (GP_ERROR);
	}

	/* Download the required image */
	if (type == GP_FILE_TYPE_NORMAL)
		id = gp_context_progress_start (context, len, 
			_("Downloading image..."));
	for (i=0; i <= (len+DATA_BUFFER-1)/DATA_BUFFER ; i++) {
		unsigned char csum;
		int xret;

		xret = gp_port_read (camera->port, (char*)buf, DATA_BUFFER);
		if (xret < GP_OK) {
			if (type == GP_FILE_TYPE_NORMAL)
				gp_context_progress_stop (context, id);
			return xret; 
		}
		ret = gp_port_read (camera->port, (char*)&csum, CSUM_LEN);
		if (ret < GP_OK) {
			if (type == GP_FILE_TYPE_NORMAL)
				gp_context_progress_stop (context, id);
			return ret;
		}
		if ((k_calculate_checksum(buf, DATA_BUFFER)) != csum) {
			if (type == GP_FILE_TYPE_NORMAL)
				gp_context_progress_stop (context, id);
			/* acknowledge the packet */
			ack = NACK;
			ret = gp_port_write (camera->port, (char*)&ack, ACK_LEN);
			if (ret < GP_OK)
				return ret;
			gp_context_error(context, _("Data has been corrupted."));
			return (GP_ERROR_CORRUPTED_DATA);
		}
		if ((len - bytes_read) > DATA_BUFFER) {
			memcpy((char *)buffer, buf, xret);
			buffer += DATA_BUFFER;
		} else {
			memcpy((char *)buffer, buf, (len - bytes_read));
			buffer += len - bytes_read;
		}

		/* acknowledge the packet */
		ack = ACK; 
		ret = gp_port_write (camera->port, (char*)&ack, ACK_LEN);
		if (ret < GP_OK) {
			if (type == GP_FILE_TYPE_NORMAL)
				gp_context_progress_stop (context, id);
			return ret;
		}
		ret = gp_port_read (camera->port, (char*)&state, STATE_LEN);
		if (ret < GP_OK) {
			if (type == GP_FILE_TYPE_NORMAL)
				gp_context_progress_stop (context, id);
			return ret;
		}
		if (state == EOT)
			break;
		bytes_read += DATA_BUFFER;
		if (type == GP_FILE_TYPE_NORMAL)
			gp_context_progress_update (context, id, bytes_read);
	}
	/* acknowledge the packet */
	ack = ACK; 
	ret = gp_port_write (camera->port, (char*)&ack, ACK_LEN);
	if (ret < GP_OK) {
		if (type == GP_FILE_TYPE_NORMAL)
			gp_context_progress_stop (context, id);
		return ret;
	}
	if (type == GP_FILE_TYPE_NORMAL)
		gp_context_progress_stop (context, id);
	return (GP_OK);
}
Пример #23
0
uint16_t
ptp_usb_getdata (PTPParams* params, PTPContainer* ptp, PTPDataHandler *handler)
{
	uint16_t ret;
	PTPUSBBulkContainer usbdata;
	unsigned char	*data = NULL;
	uint32_t	bytes_to_read, bytes_read;
	Camera		*camera = ((PTPData *)params->data)->camera;
	int		report_progress, progress_id = 0, do_retry = TRUE, res = GP_OK;
	GPContext *context = ((PTPData *)params->data)->context;

	GP_LOG_D ("Reading PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code));
	PTP_CNT_INIT(usbdata);

	ret = ptp_usb_getpacket (params, &usbdata, &bytes_read);
	if (ret != PTP_RC_OK)
		goto exit;
	if (dtoh16(usbdata.type) != PTP_USB_CONTAINER_DATA) {
		/* We might have got a response instead. On error for instance. */
		/* TODO: check if bytes_read == usbdata.length */
		if (dtoh16(usbdata.type) == PTP_USB_CONTAINER_RESPONSE) {
			params->response_packet = malloc(dtoh32(usbdata.length));
			if (!params->response_packet) return PTP_RC_GeneralError;
			memcpy(params->response_packet, (uint8_t *) &usbdata, dtoh32(usbdata.length));
			params->response_packet_size = dtoh32(usbdata.length);
			ret = PTP_RC_OK;
		} else {
			ret = PTP_ERROR_DATA_EXPECTED;
		}
		goto exit;
	}
	if (dtoh16(usbdata.code)!=ptp->Code) {
		/* A creative Zen device breaks down here, by leaving out
			 * Code and Transaction ID */
		if (MTP_ZEN_BROKEN_HEADER(params)) {
			GP_LOG_D ("Read broken PTP header (Code is %04x vs %04x), compensating.",
				  dtoh16(usbdata.code), ptp->Code);
			usbdata.code = dtoh16(ptp->Code);
			usbdata.trans_id = htod32(ptp->Transaction_ID);
		} else {
			GP_LOG_E ("Read broken PTP header (Code is %04x vs %04x).",
				  dtoh16(usbdata.code), ptp->Code );
			ret = PTP_ERROR_IO;
			goto exit;
		}
	}
	if (bytes_read > dtoh32(usbdata.length)) {
		/*
		 * Buffer the surplus response packet if it is >=
		 * PTP_USB_BULK_HDR_LEN
		 * (i.e. it is probably an entire package)
		 * else discard it as erroneous surplus data.
		 * This will even work if more than 2 packets appear
		 * in the same transaction, they will just be handled
		 * iteratively.
		 *
		 * Marcus observed stray bytes on iRiver devices;
		 * these are still discarded.
		 */
		uint32_t surplen = bytes_read - dtoh32(usbdata.length);

		if (surplen >= PTP_USB_BULK_HDR_LEN) {
			params->response_packet = malloc(surplen);
			if (!params->response_packet) return PTP_RC_GeneralError;
			memcpy(params->response_packet, (uint8_t *) &usbdata + dtoh32(usbdata.length), surplen);
			params->response_packet_size = surplen;
		} else {
			GP_LOG_D ("Read %ld bytes too much, expect problems!",
				  (long)(bytes_read - dtoh32(usbdata.length)));
		}
		bytes_read = dtoh32(usbdata.length);
	}

	/* For most PTP devices rlen is 512 == sizeof(usbdata)
	 * here. For MTP devices splitting header and data it might
	 * be PTP_USB_BULK_HDR_LEN (12).
	 */
	/* autodetect split header/data MTP devices */
	if (dtoh32(usbdata.length) > PTP_USB_BULK_HDR_LEN && (bytes_read==PTP_USB_BULK_HDR_LEN))
		params->split_header_data = 1;

	/* Copy the payload bytes we already read (with the first usb packet) */
	ret = handler->putfunc (params, handler->priv, bytes_read - PTP_USB_BULK_HDR_LEN, usbdata.payload.data);
	if (ret != PTP_RC_OK)
		goto exit;

	/* Check if we are done already... */
	if (bytes_read >= dtoh32(usbdata.length))
		goto exit;

	/* If not read the rest of it. */
	/* Make bytes_to_read contain the number of remaining payload-bytes to read. */
	bytes_to_read = dtoh32(usbdata.length) - bytes_read;
	/* Make bytes_read contain the number of payload-bytes already read. */
	bytes_read -= PTP_USB_BULK_HDR_LEN;

	data = malloc(READLEN);
	if (!data) return PTP_RC_GeneralError;

	report_progress = (bytes_to_read > 2*CONTEXT_BLOCK_SIZE) && (dtoh32(usbdata.length) != 0xffffffffU);
	if (report_progress)
		progress_id = gp_context_progress_start (context, (bytes_to_read/CONTEXT_BLOCK_SIZE), _("Downloading..."));
	while (bytes_to_read > 0) {
		unsigned long chunk_to_read = bytes_to_read;

		/* if in read-until-short-packet mode, read one packet at a time */
		/* else read in large blobs */
		/* else read all but the last short packet depending on EP packetsize. */
		if (dtoh32(usbdata.length) == 0xffffffffU)
			chunk_to_read = PTP_USB_BULK_HS_MAX_PACKET_LEN_READ;
		else if (chunk_to_read > READLEN)
			chunk_to_read = READLEN;
		else if (chunk_to_read > params->maxpacketsize)
			chunk_to_read = chunk_to_read - (chunk_to_read % params->maxpacketsize);
		res = gp_port_read (camera->port, (char*)data, chunk_to_read);
		if (res == GP_ERROR_IO_READ && do_retry) {
			GP_LOG_D ("Clearing halt on IN EP and retrying once.");
			gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_IN);
			/* retrying only once and only if we did not read anything yet */
			do_retry = FALSE;
			continue;
		} else if (res <= 0) {
			ret = PTP_ERROR_IO;
			break;
		} else
			do_retry = FALSE; /* once we have succesfully read any data, don't try again */
		ret = handler->putfunc (params, handler->priv, res, data);
		if (ret != PTP_RC_OK)
			break;
		if (dtoh32(usbdata.length) == 0xffffffffU) {
			/* once we have read a short packet, we are done. */
			if (res < PTP_USB_BULK_HS_MAX_PACKET_LEN_READ)
				bytes_to_read = 0;
		} else
			bytes_to_read -= res;
		bytes_read += res;
		if (report_progress && ((bytes_read-res)/CONTEXT_BLOCK_SIZE < bytes_read/CONTEXT_BLOCK_SIZE))
			gp_context_progress_update (context, progress_id, bytes_read/CONTEXT_BLOCK_SIZE);
		/* Only cancel transfers larger than 1MB. as
		 * canceling did not work on eos_get_viewfinder of 200kb */
		if ((bytes_read > 1024*1024) && gp_context_cancel(context) == GP_CONTEXT_FEEDBACK_CANCEL) {
			ret = PTP_ERROR_CANCEL;
			break;
		}
	}
	if (report_progress)
		gp_context_progress_stop (context, progress_id);

exit:
	free (data);

	if ((ret!=PTP_RC_OK) && (ret!=PTP_ERROR_CANCEL)) {
		GP_LOG_E ("PTP_OC 0x%04x receiving data failed: %s (0x%04x)", ptp->Code, ptp_strerror(ret, params->deviceinfo.VendorExtensionID), ret);
		return PTP_ERROR_IO;
	}
	return ret;
}
Пример #24
0
/* This function reads all thumbnails at once and initializes the whole
 * camera filesystem. This can be done, because finding out how much 
 * pictures are on the camera is done by reading the whole preview picture
 * stream anyway.
 * And since the file infos are static mostly, why not just set them too at
 * the same time.
 */
int
jd11_index_reader(GPPort *port, CameraFilesystem *fs, GPContext *context) {
    int		i, id, count, xsize, curread=0, ret=0;
    unsigned char	*indexbuf;

    ret = jd11_select_index(port);
    if (ret != GP_OK)
	return ret;
    xsize = jd11_imgsize(port);
    if (!xsize) { /* shortcut, no reading needed */
	return GP_OK;
    }
    count = xsize/(64*48);
    xsize = count * (64*48);
    indexbuf = malloc(xsize);
    if (!indexbuf) return GP_ERROR_NO_MEMORY;
    id = gp_context_progress_start (context, xsize,
				    _("Downloading thumbnail..."));
    _send_cmd(port,0xfff1);
    while (curread < xsize) {
	    int readsize = xsize-curread;
	    if (readsize>200) readsize = 200;
	    ret=getpacket(port,indexbuf+curread,readsize);
	    if (ret==0)
		    break;
	    curread+=ret;
	    if (ret<200)
		    break;
	    gp_context_progress_update (context, id, curread);
	    if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
		/* What to do...Just free the stuff we allocated for now.*/
		free(indexbuf);
		return GP_ERROR_CANCEL;
	    }
	    _send_cmd(port,0xfff1);
    }
    gp_context_progress_stop (context, id);
    for (i=0;i<count;i++) {
	CameraFile	*file;
	char		fn[20];
	unsigned char *src;
	unsigned char thumb[64*48];
	int y;
	CameraFileInfo	info;
	
	ret = gp_file_new(&file);
	if (ret!=GP_OK) {
	    free(indexbuf);
	    return ret;
	}
	sprintf(fn,"image%02i.pgm",i);
	gp_file_set_mime_type(file, GP_MIME_PGM);
	gp_file_append(file, THUMBHEADER, strlen(THUMBHEADER));
	src = indexbuf+(i*64*48);
	for (y=0;y<48;y++) {
	    int x,off = 64*y;
	    for (x=0;x<64;x++)
		thumb[47*64-off+(63-x)] = src[off+x];
	}
	ret = gp_file_append(file,(char*)thumb,sizeof(thumb));
	if (ret != GP_OK) {
		gp_file_free (file);
		return ret;
	}
	ret = gp_filesystem_append(fs, "/", fn, context);
	if (ret != GP_OK) {
		/* should perhaps remove the entry again */
		gp_file_free (file);
		return ret;
	}
	ret = gp_filesystem_set_file_noop(fs, "/", fn, GP_FILE_TYPE_PREVIEW, file, context);
	if (ret != GP_OK) return ret;

	/* we also get the fs info for free, so just set it */
	info.file.fields = GP_FILE_INFO_TYPE |
			GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT | 
			GP_FILE_INFO_SIZE;
	strcpy(info.file.type,GP_MIME_PNM);
	info.file.width		= 640;
	info.file.height	= 480;
	info.file.size		= 640*480*3+strlen(IMGHEADER);
	info.preview.fields = GP_FILE_INFO_TYPE |
			GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT | 
			GP_FILE_INFO_SIZE;
	strcpy(info.preview.type,GP_MIME_PGM);
	info.preview.width	= 64;
	info.preview.height	= 48;
	info.preview.size	= 64*48+strlen(THUMBHEADER);
	ret = gp_filesystem_set_info_noop(fs, "/", fn, info, context);
    }
    free(indexbuf);
    return GP_OK;
}