/* * 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 */
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; }
/* * 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; }
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); }
/* * 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); }
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; }
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); }
/* * 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 */
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)); }
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; }
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; }
/* * 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); }
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); }
/* 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); }
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); }
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); }
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); }
/* 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; }
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); }
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; }
/* * 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); }
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; }
/* 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; }