/****************************************************************/ /* jamcam.c - Gphoto2 library for the KBGear JamCam v2 and v3 */ /* */ /* Copyright 2001 Chris Pinkham */ /* */ /* Author: Chris Pinkham */ /* */ /* This library is free software; you can redistribute it */ /* and/or modify it under the terms of the GNU Library General */ /* Public License as published by the Free Software Foundation; */ /* either version 2 of the License, or (at your option) any */ /* later version. */ /* */ /* This library is distributed in the hope that it will be */ /* useful, but WITHOUT ANY WARRANTY; without even the implied */ /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */ /* PURPOSE. See the GNU Library General Public License for */ /* more details. */ /* */ /* You should have received a copy of the GNU Library General */ /* Public License along with this library; if not, write to the */ /* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,*/ /* Boston, MA 02110-1301 USA */ /****************************************************************/ #include "config.h" #include #include #include #include #include #include #include "libgphoto2/i18n.h" #include "library.h" #define GP_MODULE "jamcam" #define TIMEOUT 2000 #define JAMCAM_VERSION "0.6" #define JAMCAM_LAST_MOD "11/28/2001 14:51 EST" /* define what cameras we support */ static const struct { char *model; int usb_vendor; int usb_product; } models[] = { { "KBGear:JamCam", 0x084E, 0x0001 }, { NULL, 0, 0 } }; int camera_id (CameraText *id) { /* GP_DEBUG ("* camera_id"); */ strcpy (id->text, "jamcam"); return (GP_OK); } int camera_abilities (CameraAbilitiesList *list) { int x = 0; char *ptr; CameraAbilities a; /* GP_DEBUG ("* camera_abilities"); */ ptr = models[x].model; while (ptr) { memset(&a, 0, sizeof(a)); strcpy (a.model, ptr ); a.status = GP_DRIVER_STATUS_PRODUCTION; a.port = GP_PORT_SERIAL | GP_PORT_USB; a.speed[0] = 57600; a.speed[1] = 0; /* fixme, need to set these operations lists to correct values */ a.operations = GP_OPERATION_NONE; a.file_operations = GP_FILE_OPERATION_PREVIEW; a.folder_operations = GP_FOLDER_OPERATION_NONE; a.usb_vendor = models[x].usb_vendor; a.usb_product = models[x].usb_product; gp_abilities_list_append (list, a); ptr = models[++x].model; } return (GP_OK); } static int file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list, void *data, GPContext *context) { Camera *camera = data; int count; GP_DEBUG ("* file_list_func"); GP_DEBUG ("*** folder: %s", folder); CHECK (count = jamcam_file_count (camera)); CHECK (gp_list_populate (list, "pic_%04i.ppm", count)); return (GP_OK); } static int get_info_func (CameraFilesystem *fs, const char *folder, const char *filename, CameraFileInfo *info, void *data, GPContext *context) { Camera *camera = data; int n; struct jamcam_file *jc_file; GP_DEBUG ("* get_info_func"); GP_DEBUG ("*** folder: %s", folder); GP_DEBUG ("*** filename: %s",filename); /* Get the file number from the CameraFileSystem */ CHECK (n = gp_filesystem_number (camera->fs, folder, filename, context)); jc_file = jamcam_file_info( camera, n ); /* fixme, get file size also */ info->file.fields = GP_FILE_INFO_TYPE; strcpy (info->file.type, GP_MIME_PPM); info->file.width = jc_file->width; info->file.height = jc_file->height; info->preview.fields = GP_FILE_INFO_TYPE; strcpy (info->preview.type, GP_MIME_PPM); info->preview.width = 80; info->preview.height = 60; return (GP_OK); } static int camera_exit (Camera *camera, GPContext *context) { GP_DEBUG ("* camera_exit"); jamcam_file_count (camera); return (GP_OK); } #define CHECK_free(result) { \ int res; \ res = result; \ if (res < 0) { \ free(raw); free(ppm); \ return (res); \ } \ } 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; char *raw, *ppm; unsigned char gtable[256]; char *ptr; unsigned int size = 0; int n = 0; int width, height; struct jamcam_file *jc_file; GP_DEBUG ("* camera_file_get"); GP_DEBUG ("*** folder: %s", folder); GP_DEBUG ("*** filename: %s",filename); GP_DEBUG ("*** type: %d", type); CHECK (n = gp_filesystem_number (camera->fs, folder, filename, context)); if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) return (GP_ERROR_CANCEL); raw = malloc(640*480 * 3); ppm = malloc(640*480 * 3 + 200); switch (type) { case GP_FILE_TYPE_PREVIEW: CHECK_free (jamcam_request_thumbnail (camera, file, raw, &size, n, context)); width = 80; height = 60; sprintf( ppm, "P6\n" "# CREATOR: gphoto2, jamcam library\n" "%d %d\n" "255\n", width, height ); ptr = ppm + strlen( ppm ); size = strlen( ppm ) + ( height * width * 3 ); gp_bayer_decode((unsigned char *)raw, width, height, (unsigned char *)ptr, BAYER_TILE_GBRG ); gp_gamma_fill_table( gtable, 0.5 ); gp_gamma_correct_single( gtable, (unsigned char *)ptr, height * width ); CHECK_free (gp_file_set_mime_type (file, GP_MIME_PPM)); CHECK_free (gp_file_append (file, ppm, size)); break; case GP_FILE_TYPE_NORMAL: CHECK_free (jamcam_request_image (camera, file, raw, &size, n, context)); jc_file = jamcam_file_info (camera, n); sprintf( ppm, "P6\n" "# CREATOR: gphoto2, jamcam library\n" "%d %d\n" "255\n", jc_file->width, jc_file->height ); if ((jc_file->width > 640) || (jc_file->height > 480)) { free (raw); free (ppm); return GP_ERROR; } ptr = ppm + strlen( ppm ); size = strlen( ppm ) + ( jc_file->width * jc_file->height * 3 ); gp_bayer_decode((unsigned char *)raw, jc_file->width, jc_file->height, (unsigned char *)ptr, BAYER_TILE_GBRG ); gp_gamma_fill_table( gtable, 0.5 ); gp_gamma_correct_single( gtable, (unsigned char *)ptr, jc_file->width * jc_file->height ); CHECK_free (gp_file_set_mime_type (file, GP_MIME_PPM)); CHECK_free (gp_file_append (file, ppm, size)); break; case GP_FILE_TYPE_RAW: CHECK_free (jamcam_request_image (camera, file, raw, &size, n, context)); CHECK_free (gp_file_set_mime_type (file, GP_MIME_RAW)); CHECK_free (gp_file_append (file, raw, size)); break; default: free(raw); free(ppm); return (GP_ERROR_NOT_SUPPORTED); } free(raw); free(ppm); return (GP_OK); } static int camera_summary (Camera *camera, CameraText *summary, GPContext *context) { int count; char tmp[1024]; GP_DEBUG ("* camera_summary"); /* possibly get # pics, mem free, etc. */ count = jamcam_file_count (camera); sprintf (tmp, _("Frames Taken : %4d\n"), count); strcat (summary->text, tmp ); return (GP_OK); } static int camera_about (Camera *camera, CameraText *about, GPContext *context) { GP_DEBUG ("* camera_about"); strcpy (about->text, _("jamcam library v" JAMCAM_VERSION " " JAMCAM_LAST_MOD "\n" "Chris Pinkham \n" "Support for KBGear JamCam v2.0 & v3.0 digital cameras\n" "based on reverse engineering serial protocol.\n" "\n")); return (GP_OK); } static CameraFilesystemFuncs fsfuncs = { .file_list_func = file_list_func, .get_file_func = get_file_func, .get_info_func = get_info_func, }; int camera_init (Camera *camera, GPContext *context) { int count; GPPortSettings settings; GP_DEBUG ("* camera_init"); GP_DEBUG (" * jamcam library for Gphoto2 by Chris Pinkham "); GP_DEBUG (" * jamcam library v%s, %s", JAMCAM_VERSION, JAMCAM_LAST_MOD ); /* First, set up all the function pointers */ camera->functions->exit = camera_exit; camera->functions->summary = camera_summary; camera->functions->about = camera_about; CHECK (gp_port_get_settings (camera->port, &settings)); switch( camera->port->type ) { case GP_PORT_SERIAL: settings.serial.speed = 57600; settings.serial.bits = 8; settings.serial.parity = 0; settings.serial.stopbits = 1; break; case GP_PORT_USB: /* Use the defaults the core parsed */ break; default: fprintf( stderr, "Unknown port type: %d\n", camera->port->type ); return ( GP_ERROR ); break; } CHECK (gp_port_set_settings (camera->port, settings)); CHECK (gp_port_set_timeout (camera->port, TIMEOUT)); /* check to see if camera is really there */ CHECK (jamcam_enq (camera)); /* get number of images */ CHECK (count = jamcam_file_count (camera)); /* Set up the CameraFilesystem */ return gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera); }