diff --git a/camlibs/digigr8/ChangeLog b/camlibs/digigr8/ChangeLog index 6857781f6..b2cc036b6 100644 --- a/camlibs/digigr8/ChangeLog +++ b/camlibs/digigr8/ChangeLog @@ -1,3 +1,10 @@ +2007-07-16 Theodore Kilgore + * library.c: "Disney pix micro" camera supports "delete all." + Also, digigr8 cameras will do capture_preview. These two functions added. + 0x9050 cameras need to be distinguished from 0x905C cameras. + * digigr8.c: camera functions to support deletion and capture. + * digigr8.h: necessary changes. + 2007-07-12 Theodore Kilgore * library.c: "Disney pix micro" camera, 0x2770:0x9050, works with this driver. Added it. diff --git a/camlibs/digigr8/README.digigr8 b/camlibs/digigr8/README.digigr8 index d8a67f234..daf5329d6 100644 --- a/camlibs/digigr8/README.digigr8 +++ b/camlibs/digigr8/README.digigr8 @@ -51,6 +51,7 @@ WHAT FEATURES DO THESE CAMERAS HAVE, AND WHAT DOES THIS DRIVER SUPPORT? -- Ability to download the first k pictures, where k is less than the number on the camera Y -- Ability to download individual photos Y (faked, but works) +-- Shoot a frame and save image to computer Y -- Internal battery, which recharges through the USB port (some models) ------------------------------------------------------------------------- @@ -74,12 +75,17 @@ The following things can be done with button-pushes on the camera: Notes: +One camera has been discovered, in July 2007, to which the above list does +not correspond. See the section "More concerning the newly discovered +0x2770:0x9050 camera". + The only known cameras supported by the camlibs/digigr8 have a 640x480 high-resolution setting and a 320x240 low-resolution setting. If your 0x2770:0x905c camera uses another resolution setting, then it might still work. There is some similarity with the sq905 cameras, and I kept that part of the code here. Specifically, if the camera has 352x288 and 176x144 -resolution settings, these might work but are not tested. If your camera does +resolution settings, these might work but are not tested (Note added July 2007: +the code for 352x288 _does_ continue to work; see below). If your camera does not work due to unknown resolution settings, then the new resolution settings need to be listed in digigr8.c in digi_get_picture_width (). Please report any such problem. I will ask you to run a gphoto2 command in debug mode and we can @@ -190,11 +196,17 @@ the compression algorithm is the same as that in the 0x905C cameras, this new camera is quite usable, for what it is. Resolution for this camera is fixed at 352x288 and can not be adjusted. In fact, the only thing on the camera which can be controlled at all, aside from snapping photos one at a time, is to -delete photos one at a time, starting from the last one (one has to press the -delete button on the camera and the shutter button on the camera to delete one -picture). No clip option, no delayed-shooting option, no multiple frames for AVI -images. In summary, this is a very rudimentary camera, even more so than other -SQ cameras. +delete photos one at a time or to delete all. To delete one photo with the +delete button on the camera, press the button. To delete all, hold it down +longer. The camera has no clip option, no delayed-shooting option, and no +multi-frame clips intended for AVI images. However, the camera will do +software deletion of all photos using the option gphoto2 -D, while for the +other cameras supported in camlibs/digigr8 the gphoto2 -D option does nothing +at all. However: + +The USB command to delete is the same as the command to shoot a frame +(gphoto2 option is --capture-preview). If you shoot a frame with the Disney +pix micro, it will deledte whatever photos are on the camera !!! @@ -218,4 +230,4 @@ WARRANTY? Theodore Kilgore 12/05/05 -(revised 12/29/05, 03/28/07, 06/25/07, 07/12/07) \ No newline at end of file +(revised 12/29/05, 03/28/07, 06/25/07, 07/16/07) \ No newline at end of file diff --git a/camlibs/digigr8/digigr8.c b/camlibs/digigr8/digigr8.c index c2f8ae199..a4e858bf2 100644 --- a/camlibs/digigr8/digigr8.c +++ b/camlibs/digigr8/digigr8.c @@ -75,7 +75,7 @@ digi_init (GPPort *port, CameraPrivateLibrary *priv) } -unsigned char +int digi_get_comp_ratio (CameraPrivateLibrary *priv, int entry) { switch (priv->catalog[16*entry]) { @@ -156,7 +156,8 @@ digi_reset (GPPort *port) return GP_OK; } -unsigned char * + +int digi_read_picture_data (GPPort *port, unsigned char *data, int size, int n ) { @@ -174,3 +175,48 @@ digi_read_picture_data (GPPort *port, unsigned char *data, int size, int n ) return GP_OK; } + +int digi_delete_all (GPPort *port, CameraPrivateLibrary *priv) +{ + int i; + int size; + int num_pics; + unsigned char *get_size; + unsigned char *junk=NULL; + get_size=malloc(0x50); + if(!get_size) + return GP_ERROR_NO_MEMORY; + num_pics = priv->nb_entries; + GP_DEBUG("number of entries is %i\n", num_pics); + digi_reset (port); + digi_reset (port); + if(!num_pics) { + GP_DEBUG("Camera is already empty!\n"); + return GP_OK; + } + SQWRITE (port, 0x0c, 0x1440, 0x110f, NULL, 0); + i=0; + while (i < 19) { + gp_port_read(port, (char *)get_size, 0x50); + GP_DEBUG("get_size[0x40] = 0x%x\n", get_size[0x40]); + size = get_size[0x40]+(get_size[0x41]*0x100); + GP_DEBUG("size = 0x%x\n", size); + if(size <= 0xff) { + free(get_size); + GP_DEBUG("Size not read. Downloading to clear camera not needed.\n"); + digi_reset(port); + return GP_OK; + } + junk = malloc(size); + if(! junk) { + GP_DEBUG("allocation of junk space failed\n"); + return GP_ERROR_NO_MEMORY; + } + gp_port_read(port, (char *)junk, size); + free(junk); + i ++; + } + digi_reset (port); + return GP_OK; +} + diff --git a/camlibs/digigr8/digigr8.h b/camlibs/digigr8/digigr8.h index cf8519b84..104dd05a0 100644 --- a/camlibs/digigr8/digigr8.h +++ b/camlibs/digigr8/digigr8.h @@ -22,19 +22,19 @@ struct _CameraPrivateLibrary { unsigned char *catalog; int nb_entries; int last_fetched_entry; + int delete_all; }; int digi_reset (GPPort *); int digi_init (GPPort *, CameraPrivateLibrary *); int digi_rewind (GPPort *port, CameraPrivateLibrary *priv); -unsigned char *digi_read_picture_data (GPPort *, unsigned char *data, +int digi_read_picture_data (GPPort *, unsigned char *data, int size, int n); /* Those functions don't need data transfer with the camera */ int digi_get_num_frames (CameraPrivateLibrary *, int entry); -unsigned -char digi_get_comp_ratio (CameraPrivateLibrary *, int entry); +int digi_get_comp_ratio (CameraPrivateLibrary *, int entry); int digi_get_data_size (CameraPrivateLibrary *, int entry); int digi_get_picture_width (CameraPrivateLibrary *, int entry); int digi_is_clip (CameraPrivateLibrary *, int entry); @@ -43,5 +43,6 @@ int digi_decompress (unsigned char *out_data, unsigned char *data, int digi_postprocess (CameraPrivateLibrary *priv, int width, int height, unsigned char* rgb, int n); +int digi_delete_all (GPPort *, CameraPrivateLibrary *priv); #endif diff --git a/camlibs/digigr8/library.c b/camlibs/digigr8/library.c index ac802c485..44db7e831 100644 --- a/camlibs/digigr8/library.c +++ b/camlibs/digigr8/library.c @@ -94,8 +94,9 @@ camera_abilities (CameraAbilitiesList *list) a.operations = GP_OPERATION_NONE; else a.operations = GP_OPERATION_CAPTURE_PREVIEW; - a.folder_operations = GP_FOLDER_OPERATION_NONE; - a.file_operations = GP_FILE_OPERATION_PREVIEW + GP_FILE_OPERATION_RAW; + a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL; + a.file_operations = GP_FILE_OPERATION_PREVIEW + + GP_FILE_OPERATION_RAW; gp_abilities_list_append (list, a); } @@ -105,7 +106,7 @@ camera_abilities (CameraAbilitiesList *list) static int camera_summary (Camera *camera, CameraText *summary, GPContext *context) { - sprintf (summary->text,_("Your USB camera has an SQ905C chipset.\n" + sprintf (summary->text,_("Your USB camera seems to have an SQ905C chipset.\n" "The total number of pictures in it is %i\n" ), @@ -119,13 +120,12 @@ static int camera_manual (Camera *camera, CameraText *manual, GPContext *context strcpy(manual->text, _( "For cameras with SQ905C Technologies chip.\n" - "Should work with gtkam. Photos will be saved in PPM format.\n\n" - "IMPORTANT: CAMERA DOES NOT SUPPORT PHOTO SELECTION!\n" - "YOU MUST DOWNLOAD ALL PHOTOS AND CULL THEM LATER !!!\n" - "These cameras do not allow deletion of all photos.\n" - "Uploading of data to the camera is not supported.\n" - "Compression mode is UNSUPPORTED. A compressed photo\n" - "is guaranteed to download as pure junk.\n" + "Photos will be saved in PPM format.\n\n" + "Some of these cameras allow software deletion of all photos.\n" + "Others do not, depending on the chip revision. \n" + "If deletion does work, then gphoto2 -- capture image will \n" + "have the side-effect that it also deletes what is on the camera.\n" + "Uploading of data to the camera not supported by hardware.\n" )); return (GP_OK); @@ -269,6 +269,79 @@ get_file_func (CameraFilesystem *fs, const char *folder, const char *filename, return status; } +static int +delete_all_func (CameraFilesystem *fs, const char *folder, void *data, + GPContext *context) +{ + Camera *camera = data; + if(!camera->pl->delete_all) + return GP_ERROR_NOT_SUPPORTED; + digi_delete_all (camera->port, camera->pl); + return GP_OK; +} + +static int +camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context) + + +{ + unsigned char get_size[0x50]; + unsigned char *raw_data; + unsigned char *frame_data; + unsigned char *ppm, *ptr; + unsigned char gtable[256]; + char filename[14] = "digi_cap.ppm"; + int size; + int w = 320; + int h = 240; + int b; + + digi_reset (camera->port); + gp_port_usb_msg_write (camera->port, 0x0c, 0x1440, 0x110f, NULL, 0); + gp_port_read(camera->port, (char *)get_size, 0x50); + GP_DEBUG("get_size[0x40] = 0x%x\n", get_size[0x40]); + b = get_size[0x40]+(get_size[0x41]*0x100); + GP_DEBUG("b = 0x%x\n", b); + raw_data = malloc(b); + if(!raw_data) { + free(raw_data); + return GP_ERROR_NO_MEMORY; + } + gp_port_read(camera->port, (char *)raw_data, b); + frame_data = malloc(w*h); + if (!frame_data) { + free(frame_data); + return GP_ERROR_NO_MEMORY; + } + digi_decompress (frame_data, raw_data, w, h); + + /* Now put the data into a PPM image file. */ + + ppm = malloc (w * h * 3 + 256); + if (!ppm) { return GP_ERROR_NO_MEMORY; } + sprintf ((char *)ppm, + "P6\n" + "# CREATOR: gphoto2, SQ905C library\n" + "%d %d\n" + "255\n", w, h); + ptr = ppm + strlen ((char*)ppm); + size = strlen ((char*)ppm) + (w * h * 3); + GP_DEBUG ("size = %i\n", size); + gp_bayer_decode (frame_data, w , h , ptr, BAYER_TILE_BGGR); + + + gp_gamma_fill_table (gtable, .5); + gp_gamma_correct_single (gtable, ptr, w * h); + gp_file_set_mime_type (file, GP_MIME_PPM); + gp_file_set_name (file, filename); + gp_file_set_data_and_size (file, (char *)ppm, size); + + digi_reset(camera->port); + + return (GP_OK); +} + + /*************** Exit and Initialization Functions ******************/ static int @@ -288,19 +361,27 @@ camera_exit (Camera *camera, GPContext *context) static CameraFilesystemFuncs fsfuncs = { .file_list_func = file_list_func, - .get_file_func = get_file_func + .get_file_func = get_file_func, + .delete_all_func = delete_all_func }; int camera_init(Camera *camera, GPContext *context) { GPPortSettings settings; + CameraAbilities abilities; int ret = 0; - /* First, set up all the function pointers */ + ret = gp_camera_get_abilities(camera,&abilities); + if (ret < 0) return ret; + GP_DEBUG("product number is 0x%x\n", abilities.usb_product); + + /* Now, set up all the function pointers */ camera->functions->summary = camera_summary; camera->functions->manual = camera_manual; camera->functions->about = camera_about; + camera->functions->capture_preview + = camera_capture_preview; camera->functions->exit = camera_exit; GP_DEBUG ("Initializing the camera\n"); @@ -317,6 +398,14 @@ camera_init(Camera *camera, GPContext *context) if (!camera->pl) return GP_ERROR_NO_MEMORY; camera->pl->catalog = NULL; camera->pl->nb_entries = 0; + switch (abilities.usb_product) { + case 0x9050: + camera->pl->delete_all = 1; + break; + default: + camera->pl->delete_all = 0; + } + /* Connect to the camera */ ret = digi_init (camera->port, camera->pl);