/* * Only need to reset the generic camera type, AFAICT - * the pocket digital never seems to need it. */ static int ultrapocket_reset(Camera *camera) { GPPortInfo oldpi; GPPort *port = camera->port; CameraAbilities cab; unsigned char cmdbuf[0x10]; gp_camera_get_abilities(camera, &cab); GP_DEBUG ("First connect since camera was used - need to reset cam"); /* * this resets the ultrapocket. Messy, but it's what the windows * software does. We only reset if it's been plugged in since * last reset. */ memset(cmdbuf, 0, 16); cmdbuf[0] = 0x28; cmdbuf[1] = 0x01; CHECK_RESULT(ultrapocket_command(port, 1, cmdbuf, 0x10)); /* -------------- */ sleep(4); /* This should do - _might_ need increasing */ CHECK_RESULT(gp_port_get_info(port, &oldpi)); CHECK_RESULT(gp_port_free(port)); CHECK_RESULT(gp_port_new(&port)); CHECK_RESULT(gp_port_set_info(port, oldpi)); CHECK_RESULT(gp_port_usb_find_device(port, cab.usb_vendor, cab.usb_product)); CHECK_RESULT(gp_port_open(port)); camera->port = port; return GP_OK; }
/** * Close connection to camera. * * @param camera a #Camera object * @param context a #GPContext object * @return a gphoto2 error code. * * Closes a connection to the camera and therefore gives other application * the possibility to access the camera, too. * * It is recommended that you * call this function when you currently don't need the camera. The camera * will get reinitialized by gp_camera_init() automatically if you try to * access the camera again. * */ int gp_camera_exit (Camera *camera, GPContext *context) { C_PARAMS (camera); GP_LOG_D ("Exiting camera ('%s')...", camera->pc->a.model); /* * We have to postpone this operation if the camera is currently * in use. gp_camera_exit will be called again if the * camera->pc->used will drop to zero. */ if (camera->pc->used) { camera->pc->exit_requested = 1; return (GP_OK); } /* Remove every timeout that is still pending */ while (camera->pc->timeout_ids_len) gp_camera_stop_timeout (camera, camera->pc->timeout_ids[0]); free (camera->pc->timeout_ids); camera->pc->timeout_ids = NULL; if (camera->functions->exit) { #ifdef HAVE_MULTI gp_port_open (camera->port); #endif camera->functions->exit (camera, context); } gp_port_close (camera->port); memset (camera->functions, 0, sizeof (CameraFunctions)); if (camera->pc->lh) { #if !defined(VALGRIND) lt_dlclose (camera->pc->lh); lt_dlexit (); #endif camera->pc->lh = NULL; } gp_filesystem_reset (camera->fs); return (GP_OK); }
/** * Initiate a connection to the \c camera. * * @param camera a #Camera * @param context a #GPContext * @return a gphoto2 error code * * Before calling this function, the * \c camera should be set up using #gp_camera_set_port_path or * #gp_camera_set_port_name and #gp_camera_set_abilities. If that has been * omitted, gphoto2 tries to autodetect any cameras and chooses the first one * if any cameras are found. It is generally a good idea to call * #gp_camera_exit after transactions have been completed in order to give * other applications the chance to access the camera, too. * */ int gp_camera_init (Camera *camera, GPContext *context) { CameraAbilities a; const char *model, *port; CameraLibraryInitFunc init_func; int result; gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Initializing camera..."); CHECK_NULL (camera); /* * Reset the exit_requested flag. If this flag is set, * gp_camera_exit will be called as soon as the camera is no * longer in use (used flag). */ camera->pc->exit_requested = 0; /* * If the model hasn't been indicated, try to * figure it out (USB only). Beware of "Directory Browse". */ if (strcasecmp (camera->pc->a.model, "Directory Browse") && !strcmp ("", camera->pc->a.model)) { CameraAbilitiesList *al; GPPortInfo pinfo; GPPortInfoList *il; int m, p; GPPortInfo info; CameraList *list; result = gp_list_new (&list); if (result < GP_OK) return result; result = gp_port_get_info (camera->port, &pinfo); if (result < GP_OK) return result; gp_log (GP_LOG_DEBUG, "gphoto2-camera", "pinfo.type %d", pinfo.type); gp_log (GP_LOG_DEBUG, "gphoto2-camera", "pinfo.path %s", pinfo.path); gp_log (GP_LOG_DEBUG, "gphoto2-camera", "pinfo.name %s", pinfo.name); gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Neither " "port nor model set. Trying auto-detection..."); /* Call auto-detect and choose the first camera */ gp_abilities_list_new (&al); gp_abilities_list_load (al, context); gp_port_info_list_new (&il); gp_port_info_list_load (il); gp_abilities_list_detect (al, il, list, context); if (!gp_list_count (list)) { gp_abilities_list_free (al); gp_port_info_list_free (il); gp_context_error (context, _("Could not detect any camera")); gp_list_free (list); return (GP_ERROR_MODEL_NOT_FOUND); } p = 0; /* if the port was set before, then use that entry. but not if it is "usb:" */ if ( (pinfo.type == GP_PORT_USB) && strlen(pinfo.path) && strcmp(pinfo.path,"usb:") ) { for (p = gp_list_count (list);p--;) { const char *xp; gp_list_get_value (list, p, &xp); if (!strcmp (xp, pinfo.path)) break; } if (p<0) { gp_context_error (context, _("Could not detect any camera at port %s"), pinfo.path); return (GP_ERROR_FILE_NOT_FOUND); } } gp_list_get_name (list, p, &model); m = gp_abilities_list_lookup_model (al, model); gp_abilities_list_get_abilities (al, m, &a); gp_abilities_list_free (al); CRSL (camera, gp_camera_set_abilities (camera, a), context, list); CRSL (camera, gp_list_get_value (list, p, &port), context, list); p = gp_port_info_list_lookup_path (il, port); gp_port_info_list_get_info (il, p, &info); gp_port_info_list_free (il); CRSL (camera, gp_camera_set_port_info (camera, info), context, list); gp_list_free (list); } if (strcasecmp (camera->pc->a.model, "Directory Browse")) { switch (camera->port->type) { case GP_PORT_NONE: gp_context_error (context, _("You have to set the " "port prior to initialization of the camera.")); return (GP_ERROR_UNKNOWN_PORT); case GP_PORT_USB: if (gp_port_usb_find_device (camera->port, camera->pc->a.usb_vendor, camera->pc->a.usb_product) != GP_OK) { CRS (camera, gp_port_usb_find_device_by_class (camera->port, camera->pc->a.usb_class, camera->pc->a.usb_subclass, camera->pc->a.usb_protocol), context); } break; default: break; } } /* Load the library. */ gp_log (GP_LOG_DEBUG, "gphoto2-camera", "Loading '%s'...", camera->pc->a.library); lt_dlinit (); camera->pc->lh = lt_dlopenext (camera->pc->a.library); if (!camera->pc->lh) { gp_context_error (context, _("Could not load required " "camera driver '%s' (%s)."), camera->pc->a.library, lt_dlerror ()); lt_dlexit (); return (GP_ERROR_LIBRARY); } /* Initialize the camera */ init_func = lt_dlsym (camera->pc->lh, "camera_init"); if (!init_func) { lt_dlclose (camera->pc->lh); lt_dlexit (); camera->pc->lh = NULL; gp_context_error (context, _("Camera driver '%s' is " "missing the 'camera_init' function."), camera->pc->a.library); return (GP_ERROR_LIBRARY); } if (strcasecmp (camera->pc->a.model, "Directory Browse")) { result = gp_port_open (camera->port); if (result < 0) { lt_dlclose (camera->pc->lh); lt_dlexit (); camera->pc->lh = NULL; return (result); } } result = init_func (camera, context); if (result < 0) { gp_port_close (camera->port); lt_dlclose (camera->pc->lh); lt_dlexit (); camera->pc->lh = NULL; memset (camera->functions, 0, sizeof (CameraFunctions)); return (result); } /* We don't care if that goes wrong */ #ifdef HAVE_MULTI gp_port_close (camera->port); #endif return (GP_OK); }
int jl2005c_init (Camera *camera, GPPort *port, CameraPrivateLibrary *priv) { char response; int model_string = 0; /* Needs to be big enough to hold (0xfff + 3) * 0x10 */ unsigned char info[0x4020]; const char camera_id[] = {0x4a, 0x4c, 0x32, 0x30, 0x30, 0x35}; int alloc_table_size; int attempts = 0; restart: alloc_table_size = 0; memset(info,0, sizeof(info)); GP_DEBUG("Running jl2005c_init\n"); if (priv->init_done) { gp_port_close(port); usleep (100000); gp_port_open(port); } set_usb_in_endpoint (camera, 0x84); gp_port_write (port, "\x08\x00", 2); usleep (10000); gp_port_write (port, "\x95\x60", 2); jl2005c_read_data (port, &response, 1); model_string = response; gp_port_write (port, "\x95\x61", 2); jl2005c_read_data (port, &response, 1); model_string += (response & 0xff) << 8; gp_port_write (port, "\x95\x62", 2); jl2005c_read_data (port, &response, 1); model_string += (response & 0xff) << 16; gp_port_write (port,"\x95\x63" , 2); jl2005c_read_data (port, &response, 1); model_string += (response & 0xff) << 24; GP_DEBUG("Model string is %08x\n", model_string); gp_port_write (port, "\x95\x64", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x95\x65", 2); jl2005c_read_data (port, &response, 1); /* Number of pix returned here, but not reliably reported */ priv->nb_entries = response & 0xff; GP_DEBUG("%d frames in the camera (unreliable!)\n", priv->nb_entries); gp_port_write (port, "\x95\x66", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x95\x67", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x95\x68", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x95\x69", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x95\x6a", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x95\x6b", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x95\x6c", 2); jl2005c_read_data (port, &response, 1); priv->data_to_read = (response &0xff)*0x100; gp_port_write (port, "\x95\x6d", 2); jl2005c_read_data (port, &response, 1); priv->data_to_read += (response&0xff); priv->total_data_in_camera = priv->data_to_read; GP_DEBUG ("blocks_to_read = 0x%lx = %lu\n", priv->data_to_read, priv->data_to_read); gp_port_write (port, "\x95\x6e", 2); jl2005c_read_data (port, &response, 1); alloc_table_size = (response & 0xff) * 0x200; GP_DEBUG("alloc_table_size = 0x%02x * 0x200 = 0x%x\n", response & 0xff, (response & 0xff) * 0x200); gp_port_write (port, "\x95\x6f", 2); jl2005c_read_data (port, &response, 1); gp_port_write (port, "\x0a\x00", 2); usleep (10000); /* Switch the inep over to 0x82. It stays there ever after. */ set_usb_in_endpoint (camera, 0x82); /* Read the first block of the allocation table. */ jl2005c_read_data (port, (char *)info, 0x200); if (strncmp(camera_id, (char*)info, 6)) { GP_DEBUG("Error downloading alloc table\n"); GP_DEBUG("Init attempted %d times\n", attempts + 1); attempts++; if (attempts == 3) { GP_DEBUG("Third try. Giving up\n"); gp_port_write(port, "\x07\x00", 2); return GP_ERROR; } goto restart; } /* Now check the number of photos. That is found in byte 13 of line 0 * of the allocation table. */ priv->nb_entries = (info[12] & 0xff) * 0x100 | (info[13] & 0xff); GP_DEBUG("Number of entries is recalculated as %d\n", priv->nb_entries); /* Just in case there was a problem, we now recalculate the total * alloc_table_size. */ alloc_table_size = priv->nb_entries * 0x10 + 0x30; if (alloc_table_size%0x200) alloc_table_size += 0x200 - (alloc_table_size%0x200); /* However, we have already just now downloaded 0x200 bytes, so * when downloading the rest of the table we correct for that and * just download whatever remains of the information block. */ if (alloc_table_size > 0x200) gp_port_read(port, (char *)info + 0x200, alloc_table_size - 0x200); memmove(priv->table, info + 0x30, alloc_table_size - 0x30); priv->model = info[6]; GP_DEBUG("Model is %c\n", priv->model); switch (priv->model) { case 0x43: case 0x44: priv->blocksize = 0x200; break; case 0x42: priv->blocksize = 0x80; break; default: GP_DEBUG("Unknown model, unknown blocksize\n"); return GP_ERROR_NOT_SUPPORTED; } GP_DEBUG("camera's blocksize = 0x%x = %d\n", priv->blocksize, priv->blocksize); /* Now a more responsible calculation of the amount of data in the * camera, based upon the allocation table. */ priv->data_to_read = info[10] * 0x100 | info[11]; priv->data_to_read -= info[8] * 0x100 | info[9]; priv->data_to_read *= priv->blocksize; priv->total_data_in_camera = priv->data_to_read; GP_DEBUG ("data_to_read = 0x%lx = %lu\n", priv->data_to_read, priv->data_to_read); GP_DEBUG ("total_data_in_camera = 0x%lx = %lu\n", priv->data_to_read, priv->data_to_read); priv->can_do_capture = 0; if (info[7] & 0x04) priv->can_do_capture = 1; priv->bytes_read_from_camera = 0; priv->bytes_put_away = 0; priv->init_done = 1; GP_DEBUG("Leaving jl2005c_init\n"); return GP_OK; }