static int try_get_camera_file(GPParams* gp_params, const char* folder, const char* filename) { int ret = 0; CameraFile *file = NULL; if ( (ret = gp_file_new (&file)) < 0) { LOG_E("gp_file_new failed %d\n", ret); return -1; } if ( (ret = gp_camera_file_get (gp_params->camera, folder, filename, GP_FILE_TYPE_NORMAL, file, gp_params->context)) < 0) { LOG_I("gp_camera_file_get: %s\n", gp_port_result_as_string(ret)); } gp_file_unref (file); return ret; }
/** * \brief Read data from port * * \param port a #GPPort * \param data a pointer to an allocated buffer * \param size the number of bytes that should be read * * Reads a specified number of bytes from the port into the supplied buffer. * It returns the number of bytes read or a negative error code. * * \return a gphoto2 error code or the amount of data read **/ int gp_port_read (GPPort *port, char *data, int size) { int retval; gp_log (GP_LOG_DATA, __func__, "Reading %i = 0x%x bytes from port...", size, size); C_PARAMS (port); CHECK_INIT (port); /* Check if we read as many bytes as expected */ CHECK_SUPP (port, "read", port->pc->ops->read); retval = port->pc->ops->read (port, data, size); if (retval < 0) { GP_LOG_E ("Reading %i = 0x%x bytes from port failed: %s (%d)", size, size, gp_port_result_as_string(retval), retval); return retval; } LOG_DATA (data, retval, size, "Read ", "from port:"); return (retval); }
/** * \brief Writes a specified amount of data to a port. * \param port a #GPPort * \param data the data to write to the port * \param size the number of bytes to write to the port * * Writes data to the port. On non-serial ports the amount of data * written is returned (and not just GP_OK). * * \return a negative gphoto2 error code or the amount of data written. **/ int gp_port_write (GPPort *port, const char *data, int size) { int retval; gp_log (GP_LOG_DATA, __func__, "Writing %i = 0x%x bytes to port...", size, size); C_PARAMS (port && data); CHECK_INIT (port); /* Check if we wrote all bytes */ CHECK_SUPP (port, "write", port->pc->ops->write); retval = port->pc->ops->write (port, data, size); if (retval < 0) { GP_LOG_E ("Writing %i = 0x%x bytes to port failed: %s (%d)", size, size, gp_port_result_as_string(retval), retval); return retval; } LOG_DATA (data, retval, size, "Wrote ", "to port:"); return (retval); }
uint16_t ptp_usb_sendreq (PTPParams* params, PTPContainer* req) { int res, towrite, do_retry = TRUE; PTPUSBBulkContainer usbreq; Camera *camera = ((PTPData *)params->data)->camera; GP_LOG_D ("Sending PTP_OC 0x%0x (%s) request...", req->Code, ptp_get_opcode_name(params, req->Code)); /* build appropriate USB container */ usbreq.length=htod32(PTP_USB_BULK_REQ_LEN- (sizeof(uint32_t)*(5-req->Nparam))); usbreq.type=htod16(PTP_USB_CONTAINER_COMMAND); usbreq.code=htod16(req->Code); usbreq.trans_id=htod32(req->Transaction_ID); usbreq.payload.params.param1=htod32(req->Param1); usbreq.payload.params.param2=htod32(req->Param2); usbreq.payload.params.param3=htod32(req->Param3); usbreq.payload.params.param4=htod32(req->Param4); usbreq.payload.params.param5=htod32(req->Param5); /* send it to responder */ towrite = PTP_USB_BULK_REQ_LEN-(sizeof(uint32_t)*(5-req->Nparam)); retry: res = gp_port_write (camera->port, (char*)&usbreq, towrite); if (res != towrite) { if (res < 0) { GP_LOG_E ("PTP_OC 0x%04x sending req failed: %s (%d)", req->Code, gp_port_result_as_string(res), res); if (res == GP_ERROR_IO_WRITE && do_retry) { GP_LOG_D ("Clearing halt on OUT EP and retrying once."); gp_port_usb_clear_halt (camera->port, GP_PORT_USB_ENDPOINT_OUT); do_retry = FALSE; goto retry; } } else GP_LOG_E ("PTP_OC 0x%04x sending req failed: wrote only %d of %d bytes", req->Code, res, towrite); return PTP_ERROR_IO; } return PTP_RC_OK; }
static int foreach_func (const char *filename, lt_ptr data) { GPPortInfoList *list = data; lt_dlhandle lh; GPPortLibraryType lib_type; GPPortLibraryList lib_list; GPPortType type; unsigned int j, old_size = list->count; int result; gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list", _("Called for filename '%s'."), filename ); lh = lt_dlopenext (filename); if (!lh) { gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list", _("Could not load '%s': '%s'."), filename, lt_dlerror ()); return (0); } lib_type = lt_dlsym (lh, "gp_port_library_type"); lib_list = lt_dlsym (lh, "gp_port_library_list"); if (!lib_type || !lib_list) { gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list", _("Could not find some functions in '%s': '%s'."), filename, lt_dlerror ()); lt_dlclose (lh); return (0); } type = lib_type (); for (j = 0; j < list->count; j++) if (list->info[j].type == type) break; if (j != list->count) { gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list", _("'%s' already loaded"), filename); lt_dlclose (lh); return (0); } result = lib_list (list); lt_dlclose (lh); if (result < 0) { gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list", _("Could not load port driver list: '%s'."), gp_port_result_as_string (result)); return (0); } for (j = old_size; j < list->count; j++){ gp_log (GP_LOG_DEBUG, "gphoto2-port-info-list", _("Loaded '%s' ('%s') from '%s'."), list->info[j].name, list->info[j].path, filename); strcpy (list->info[j].library_filename, filename); } return (0); }
static inline uint16_t ptp_usb_event (PTPParams* params, PTPContainer* event, int wait) { int result, timeout, fasttimeout; unsigned long rlen; PTPUSBEventContainer usbevent; Camera *camera = ((PTPData *)params->data)->camera; if (params->deviceinfo.VendorExtensionID == PTP_VENDOR_CANON) fasttimeout = PTP2_FAST_TIMEOUT*2; else fasttimeout = PTP2_FAST_TIMEOUT; PTP_CNT_INIT(usbevent); if (event==NULL) return PTP_ERROR_BADPARAM; switch(wait) { case PTP_EVENT_CHECK: result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent)); if (result <= 0) result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent)); break; case PTP_EVENT_CHECK_FAST: gp_port_get_timeout (camera->port, &timeout); gp_port_set_timeout (camera->port, fasttimeout); result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent)); if (result <= 0) result = gp_port_check_int (camera->port, (char*)&usbevent, sizeof(usbevent)); gp_port_set_timeout (camera->port, timeout); break; default: return PTP_ERROR_BADPARAM; } if (result < 0) { GP_LOG_E ("Reading PTP event failed: %s (%d)", gp_port_result_as_string(result), result); if (result == GP_ERROR_TIMEOUT) return PTP_ERROR_TIMEOUT; return PTP_ERROR_IO; } if (result == 0) { GP_LOG_E ("Reading PTP event failed: a 0 read occurred, assuming timeout."); return PTP_ERROR_TIMEOUT; } rlen = result; if (rlen < 8) { GP_LOG_E ("Reading PTP event failed: only %ld bytes read", rlen); return PTP_ERROR_IO; } /* Only do the additional reads for "events". Canon IXUS 2 likes to * send unrelated data. */ if ( (dtoh16(usbevent.type) == PTP_USB_CONTAINER_EVENT) && (dtoh32(usbevent.length) > rlen) ) { GP_LOG_D ("Canon incremental read (done: %ld, todo: %d)", rlen, dtoh32(usbevent.length)); gp_port_get_timeout (camera->port, &timeout); gp_port_set_timeout (camera->port, PTP2_FAST_TIMEOUT); while (dtoh32(usbevent.length) > rlen) { result = gp_port_check_int (camera->port, ((char*)&usbevent)+rlen, sizeof(usbevent)-rlen); if (result <= 0) break; rlen += result; } gp_port_set_timeout (camera->port, timeout); } /* if we read anything over interrupt endpoint it must be an event */ /* build an appropriate PTPContainer */ event->Nparam = (rlen-12)/4; event->Code = dtoh16(usbevent.code); event->SessionID=params->session_id; event->Transaction_ID=dtoh32(usbevent.trans_id); event->Param1 = dtoh32(usbevent.param1); event->Param2 = dtoh32(usbevent.param2); event->Param3 = dtoh32(usbevent.param3); return PTP_RC_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; GP_LOG_D ("Sending PTP_OC 0x%0x (%s) data...", ptp->Code, ptp_get_opcode_name(params, ptp->Code)); /* 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) { if (res < 0) GP_LOG_E ("PTP_OC 0x%04x sending data failed: %s (%d)", ptp->Code, gp_port_result_as_string(res), res); else GP_LOG_E ("PTP_OC 0x%04x sending data failed: wrote only %d of %d bytes", ptp->Code, res, wlen); 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; 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; }