Logo Search packages:      
Sourcecode: libgphoto2 version File versions

hp215.c

/*****************************************************************************
 *  Copyright (C) 2002  Jason Surprise <thesurprises1@attbi.com>             *
 *                2003  Enno Bartels   <ennobartels@t-online.de>             *
 *            2005  Marcus Meissner <marcus@jet.franken.de>              *
 *****************************************************************************
 *                                                                           *
 *  This program 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 program 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 program; see the file COPYING.LIB.  If not,      *
 *  write to the Free Software Foundation, Inc., 59 Temple Place -           *
 *  Suite 330,  Boston, MA 02111-1307, USA.                                  *
 *                                                                           *
 *****************************************************************************/


/*
    Old Maintainer : Enno Bartels <ennobartels@t-online.de> in 2002/2003
    Original author : Jason Surprise <thesurprises1@attbi.com> in 2002.
    Checksum author: Roberto Ragusa <r.ragusa@libero.it> in 2002/2003.

    Ported to libgphoto2: Marcus Meissner <marcus@jet.franken.de> in 2005.

    Camera commands:
     Global comands
                           Bytes   | 0    1cmd 2    3    4    5    6    7    8    9    10   11   12   13   14   15
    -------------------------------+----------------------------------------------------------------------------------
     init camera              8    | 0x02 0xce 0x80 0x8a 0x84 0x8d 0x83 0x03
     get camera date/time     8    | 0x02 0xc1 0x80 0x8b 0x84 0x8e 0x8d 0x03
     Get number of pics      16    | 0x02 0xc6 0x88 0x80 0x80 0x83 0x84 0x38 0x2f 0x30 0x32 0x88 0x84 0x8e 0x8b 0x03
     Delete all pics         12    | 0x02 0xb1 0x84 0x8f 0x8f 0x8f 0x8f 0x86 0x80 0x8a 0x86 0x03


     Single picture comands:
     Allways 12 bytes long
                                   | 0    1cmd 2    3    4    5    6    7    8    9    10    11
    -------------------------------+---------------------------------------------------------------
     Request for a preview         | 0x02 0xb3 0x84 0x80 ...                                 0x03
     Request for a picture         | 0x02 0xb4 0x84 0x80 ...                                 0x03
     Request date/time for preview | 0x02 0xc5 0x84 0x80 ...                                 0x03
     Request for deleting one pic  | 0x02 0xb1 0x84 0x80 ...                                 0x03

     0x02 = Startcode for a command
     0x03 = Endcode   for a command
 */

#include "config.h"

#include <stdio.h>
#include <string.h>

#include <sys/types.h>

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#include <gphoto2/gphoto2-port-log.h>
#include <gphoto2/gphoto2-library.h>
#include <gphoto2/gphoto2-result.h>

#include "crctab.h"

#ifdef ENABLE_NLS
#  include <libintl.h>
#  undef _
#  define _(String) dgettext (GETTEXT_PACKAGE, String)
#  ifdef gettext_noop
#    define N_(String) gettext_noop (String)
#  else
#    define N_(String) (String)
#  endif
#else
#  define _(String) (String)
#  define N_(String) (String)
#endif

#include "hp215.h"

enum hp215_cmd {
      SET_TIME                = 0x86,
      SET_TIME_AS_STR               = 0x87,
      SET_TIME_MODE                 = 0x88,
      SET_TIME_PERIOD               = 0x89,
      SET_XFER_PROTOCOL       = 0x8a,
      SET_AUTO_SHUTDOWN_TIME        = 0x8b,
      SET_PHOTO_NO_DISPLAY_MODE     = 0x8c,
      DO_CALIBRATION                = 0x8d,
      GET_CALIBRATION_PARAM         = 0x8e,
      SET_SHOOT_AUTO                = 0x90,
      SET_FLASH               = 0x91,
      SET_EXPOSURE                  = 0x92,
      SET_FOCUS               = 0x93,
      SET_SHUTTER             = 0x94,
      SET_RESOLUTION                = 0x95,
      SET_COMPRESSION               = 0x96,
      SET_TIMER               = 0x97,
      SET_EXT_FLASH                 = 0x98,
      SET_PIC_FORMAT                = 0x99,
      RECORD_FUNC             = 0xa2,
      SET_SHOOTING_DEBUG_MODE       = 0xa3,
      GET_INTERNAL_SHOOT_AUTO_FUNC  = 0xa4,
      SET_INTERNAL_SHOOT_PARAM      = 0xa6,
      SET_SHOOT_PARAM               = 0xa7,
      SET_REVIEW_MODE               = 0xa8,
      SET_DISPLAY_PICTURE_NO        = 0xa9,
      SET_SHOOT_MODE_BY_INDEX       = 0xaa,
      GET_SHOOT_MODE_TABLE          = 0xab,
      SET_ACTIVE_SHOOTING_MODE      = 0xac,
      TAKE_PHOTO              = 0xb0,
      DELETE_PHOTO                  = 0xb1,
      PROTECT_PHOTO                 = 0xb2,
      DOWNLOAD_THUMBNAIL            = 0xb3,
      DOWNLOAD_PHOTO                = 0xb4,
      TAKE_PREVIEW                  = 0xb5,
      SELF_TEST               = 0xb6,
      DISPLAY_PATTERN               = 0xb7,
      UPLOAD_PHOTO                  = 0xb8,
      UPLOAD_FIRMWARE               = 0xba,
      UPDATE_FIRMWARE               = 0xbb,
      DOWNLOAD_FILE_BY_NAME         = 0xbd,
      __UPDATE_FIRMWARE       = 0xbc,
      DOWNLOAD_PHOTO_FROM_ALBUM     = 0xbe,
      GET_CAMERA_CAPS               = 0xc0,
      GET_CAMERA_CURINFO            = 0xc1,
      GET_SHOOT_MODE_2        = 0xc3,
      GET_PHOTO_INFO                = 0xc5,
      GET_ALBUM_INFO                = 0xc6,
      GET_CAMERA_READY        = 0xce,
      GET_INTERNAL_SHOOT_PARAM      = 0xcf,
      CREATE_ALBUM                  = 0xd0,
      RENAME_ALBUM                  = 0xd2,
      SET_ACTIVE_ALBUM        = 0xd4,
};

/*
    Every commands looks like:
    02 AA BB .... CC CC CC CC 03

    02 - STX
    AA - cmd byte
    BB - 0x80 | argumentlength
    ... - argumentlength bytes
    CC CC CC CC   16 bit CRC split into 4 bit pieces, | 0x80
    03 - ETX

    A generic CRC is done over the buffer, starting with the CMD byte (offset 1).

    buffer[7]  = ((crc>>12) & 0xf) | 0x80;
    buffer[8]  = ((crc>>8 ) & 0xf) | 0x80;
    buffer[9]  = ((crc>>4 ) & 0xf) | 0x80;
    buffer[10] = ((crc    ) & 0xf) | 0x80;

    buffer[11] = 0x03;

*/

static int
hp_gen_cmd_blob (enum hp215_cmd cmd, int bytes, unsigned char *argdata, unsigned char **buf, int *buflen)
{
      int i, crc = 0;

      *buflen = 1+1+1+bytes+4+1; /* STX, CMD, ARGLEN, arguments, 4xCRC, ETX */
      *buf    = malloc(*buflen);
      if (!*buf)
            return GP_ERROR_NO_MEMORY;

      /* store STX */
      (*buf)[0] = STX;

      /* store CMD */
      (*buf)[1] = cmd;
      if (bytes >= 0x7d) {
            gp_log (GP_LOG_ERROR, "hp215", "Using too large argument buffer %d bytes", bytes);
            return GP_ERROR_BAD_PARAMETERS;
      }
      /* store arglen */
      (*buf)[2] = 0x80 | bytes;

      if (bytes) {
            /* store arguments */
            memcpy ((*buf)+3, argdata, bytes);
      }

      /* generate CRC over cmd, len, and arguments */
      for (i=1;i<bytes + 3;i++)
            crc = updcrc((*buf)[i], crc);

      /* store CRC */
      (*buf)[bytes+3] = ((crc >> 12) & 0xf) | 0x80;
      (*buf)[bytes+4] = ((crc >>  8) & 0xf) | 0x80;
      (*buf)[bytes+5] = ((crc >>  4) & 0xf) | 0x80;
      (*buf)[bytes+6] = ((crc >>  0) & 0xf) | 0x80;
      /* store ETX */
      (*buf)[bytes+7] = ETX;
      return GP_OK;
}

static int
hp_gen_cmd_1_16 (enum hp215_cmd cmd, unsigned short val, unsigned char **buf, int *buflen)
{
      unsigned char argbuf[4];

      argbuf[0] = ((val&0xf000)>>12) | 0x80;
      argbuf[1] = ((val&0x0f00)>> 8) | 0x80;
      argbuf[2] = ((val&0x00f0)>> 4) | 0x80;
      argbuf[3] = ((val&0x000f)    ) | 0x80;
      return hp_gen_cmd_blob (cmd, 4, argbuf, buf, buflen);
}


static int
hp_send_ack (Camera *cam)
{
      char byte = ACK;
      int ret;

      gp_log (GP_LOG_DEBUG, "hp215", "Sending ACK ... ");
      ret = gp_port_write (cam->port, &byte, 1);
      if (ret < GP_OK)
            gp_log (GP_LOG_ERROR, "hp215", "ACK sending failed with %d", ret);
      return ret;
}


static int
hp_rcv_ack (Camera *cam, char *ackval)
{
      int           ret;
      char byte = '\0';

      gp_log (GP_LOG_DEBUG, "hp215", "Receiving ACK ... ");
      ret = gp_port_read (cam->port, &byte, 1);
      if (ret < GP_OK)
            return ret;
      if (ackval)
            *ackval = byte;
      if (byte == ACK)
            return GP_OK;
      gp_log (GP_LOG_DEBUG, "hp215", "Expected ACK, but read %02x", byte);
      return GP_ERROR_IO;
}

static int
decode_u32(unsigned char **msg, int *msglen, unsigned int *val) {
      unsigned int x = 0,i;

      for (i=0;i<8;i++) {
            if (!*msglen)
                  return GP_ERROR;
            x <<= 4;
            x  |= ((**msg) & 0x0f);
            (*msg)++;
            (*msglen)--;
      }
      *val = x;
      return GP_OK;
}

static int
decode_u16(unsigned char **msg, int *msglen, unsigned short *val) {
      unsigned int x = 0,i;

      for (i=0;i<4;i++) {
            if (!*msglen)
                  return GP_ERROR;
            x <<= 4;
            x  |= ((**msg) & 0x0f);
            (*msg)++;
            (*msglen)--;
      }
      *val = x;
      return GP_OK;
}

static int
hp_send_command_and_receive_blob(
      Camera *camera, unsigned char *buf, int buflen,
      unsigned char **msg, int *msglen, unsigned int *retcode
) {
      int tries, ackret, ret, replydatalen;
      unsigned char msgbuf[0x400];
      char ackval;

      tries = 0;
      *msg = NULL;
      *msglen = 0;
      for (tries = 0; tries < 3; tries++ ) {
            ret = gp_port_write (camera->port, (char*)buf, buflen);
            if (ret < GP_OK)
                  return ret;
            ret = hp_rcv_ack (camera, &ackval);
            if (ret < GP_OK) {
                  if (ackval == NAK)
                        continue;
                  return GP_ERROR_IO;
            }
            break;
      }
      gp_log( GP_LOG_DEBUG, "hp215", "Expecting reply blob");
      ret = gp_port_read (camera->port, (char*)msgbuf, sizeof(msgbuf));
      if (ret < GP_OK)
            return ret;
      ackret = hp_send_ack (camera);
      if (ackret < GP_OK)
            return ackret;
      if (msgbuf[0] != STX) {
            gp_log (GP_LOG_ERROR, "hp215", "Expected STX / 02 at begin of buffer, found %02x", msgbuf[0]);
            return GP_ERROR_IO;
      }
      if (msgbuf[ret-1] != ETX) {
            gp_log (GP_LOG_ERROR, "hp215", "Expected ETX / 03 at end of buffer, found %02x", msgbuf[ret-1]);
            return GP_ERROR_IO;
      }
      replydatalen = msgbuf[2] & 0x7f;
      if (replydatalen != ret - 8) {
            gp_log (GP_LOG_ERROR, "hp215", "Reply datablob length says %d, but just %d bytes available?", replydatalen, ret-8);
            return GP_ERROR_IO;
      }
      if (replydatalen < 2) {
            gp_log (GP_LOG_ERROR, "hp215", "Reply datablob length is smaller than retcode (%d)", replydatalen);
            return GP_ERROR_IO;
      }
      *retcode = (msgbuf[3] << 8) | msgbuf[4];

      if (msgbuf[2] == 0xff) {
            unsigned char *xmsg = msgbuf+5;
            int xmsglen = 8;
            unsigned int newlen;
            char eot;
            /* ok, overlong reply */

            ret = decode_u32(&xmsg, &xmsglen, &newlen);
            if (ret < GP_OK)
                  return ret;
            replydatalen = newlen;
            *msglen = replydatalen;
            *msg = malloc (replydatalen);
            ret = gp_port_read (camera->port, (char*)*msg, replydatalen);
            if (ret < GP_OK)
                  return ret;
            ret = gp_port_read (camera->port, &eot, 1);
            if (ret < GP_OK)
                  return ret;
            if (ret != 1)
                  return GP_ERROR_IO;
            if (eot != EOT) {
                  gp_log (GP_LOG_ERROR, "hp215", "read %02x instead of expected 04", eot);
                  return GP_ERROR_IO;
            }
            ackret = hp_send_ack (camera);
            if (ackret < GP_OK)
                  return ackret;
      } else {
            /* short reply - normal mode, do not copy E0 E0  */
            *msg = malloc (replydatalen-2);
            *msglen = replydatalen-2;
            memcpy (*msg, msgbuf+5, replydatalen-2);
      }
      gp_log (GP_LOG_DEBUG, "hp215", "Read Blob: retcode is %04x", *retcode);
      gp_log (GP_LOG_DEBUG, "hp215", "Read Blob: argument block is:");
      gp_log_data ("hp215", (char*)*msg, *msglen);
      return GP_OK;
}

static int
hp_get_timeDate_cam (Camera *cam, char *txtbuffer, size_t txtbuffersize)
{
      int         msglen, buflen, ret;
      unsigned char     *xmsg, *msg, *buf;
      unsigned int      retcode;
      t_date            date;
      unsigned short    val16;
      unsigned int      percent, val32, freespace, unixtime, freeimages, usedimages;
      char        datebuf[15];

      gp_log (GP_LOG_DEBUG, "hp215", "Sending date/time command ... ");

      ret = hp_gen_cmd_blob (GET_CAMERA_CURINFO, 0, NULL, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (cam, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      xmsg = msg;
      if (msglen < 0x59) {
            gp_log (GP_LOG_ERROR, "hp215", "too short reply block, %d bytes", msglen);
            return GP_ERROR_IO;
      }
      
      memcpy (datebuf, msg, 15);
      gp_log (GP_LOG_DEBUG, "hp215", "0f: %02x", msg[0x0f] & 0x7f);
      gp_log (GP_LOG_DEBUG, "hp215", "10: %02x", msg[0x10] & 0x7f);

      xmsg += 0x12;
      msglen -= 0x12;
      decode_u16(&xmsg, &msglen, &val16);
      gp_log (GP_LOG_DEBUG, "hp215", "12: %04x", val16);
      gp_log (GP_LOG_DEBUG, "hp215", "16: %02x", msg[0x16] & 0x7f);
      xmsg++;msglen--;
      decode_u16(&xmsg, &msglen, &val16);
      gp_log (GP_LOG_DEBUG, "hp215", "17: %04x", val16);
      decode_u16(&xmsg, &msglen, &val16);
      gp_log (GP_LOG_DEBUG, "hp215", "1b: %04x", val16);
      percent = msg[0x1f] & 0x7f;
      xmsg++;msglen--;
      decode_u32(&xmsg, &msglen, &val32);
      gp_log (GP_LOG_DEBUG, "hp215", "20: %08x", val32);
      decode_u32(&xmsg, &msglen, &val32);
      gp_log (GP_LOG_DEBUG, "hp215", "28: %08x", val32);
      decode_u32(&xmsg, &msglen, &val32);
      gp_log (GP_LOG_DEBUG, "hp215", "30: %08x", val32);
      gp_log (GP_LOG_DEBUG, "hp215", "38: %02x", msg[0x38] & 0x7f);
      xmsg++;msglen--;
      decode_u32(&xmsg, &msglen, &unixtime);
      decode_u32(&xmsg, &msglen, &freeimages);
      decode_u32(&xmsg, &msglen, &usedimages);
      decode_u32(&xmsg, &msglen, &val32);
      gp_log (GP_LOG_DEBUG, "hp215", "51: %08x", val32);
      decode_u32(&xmsg, &msglen, &freespace);

      /* Filter time and date out of the message */
      date.day   = (msg[3]-48)*10 + (msg[4]-48);
      date.month = (msg[0]-48)*10 + (msg[1]-48);
      date.year  = 2000 + (msg[6]-48)*10 + (msg[7]-48);
      date.hour  = (msg[9]-48)*10 + (msg[10]-48);
      date.min   = (msg[12]-48)*10 + (msg[13]-48);
      free (msg);


      snprintf (txtbuffer, txtbuffersize, _("Current camera time:  %04d-%02d-%02d  %02d:%02d\nFree card memory: %d\nImages on card: %d\nImages free on card: %d\nBattery level: %d %%"),
            date.year, date.month, date.day, date.hour, date.min,
            freespace, usedimages, freeimages, percent
      );
      /* FIXME: communication hangs here ... perhaps need to reset USB pipe */
      return GP_OK;
}

static int
camera_summary (Camera *camera, CameraText *summary, GPContext *context)
{
      char  buffer[200];
      int   ret;

      ret = hp_get_timeDate_cam (camera, buffer, sizeof(buffer));
      if (ret < GP_OK)
            return ret;
      strcpy (summary->text, buffer);
      return (GP_OK);
}

static int
camera_about (Camera *camera, CameraText *about, GPContext *context)
{
      strcpy (about->text, _("hp215\n"
                        "Marcus Meissner <marcus@jet.franken.de>\n"
                        "Driver to access the HP Photosmart 215 camera.\n"
                        "Merged from the standalone hp215 program.\n"
                        "This driver allows download of images and previews, and deletion of images.\n"
      ));
      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           ret, buflen, msglen, image_no;
      unsigned char cmd, *buf, *msg;
      unsigned int  retcode;

      image_no = gp_filesystem_number(fs, folder, filename, context);
      if(image_no < 0)
            return image_no;

      switch (type) {
      case GP_FILE_TYPE_NORMAL:
            cmd = DOWNLOAD_PHOTO;
            break;
      case GP_FILE_TYPE_PREVIEW:
            cmd = DOWNLOAD_THUMBNAIL;
            break;
      default:
            return GP_ERROR_BAD_PARAMETERS;
      }

      ret = hp_gen_cmd_1_16 (cmd, image_no+1, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      gp_file_set_mime_type (file, GP_MIME_JPEG);
      gp_file_set_data_and_size (file, (char*)msg, msglen);
      /* do not free (msg), we handed it to the lower layer right now */
      return GP_OK;
}

static int
delete_file_func (CameraFilesystem *fs, const char *folder,
              const char *filename, void *data, GPContext *context)
{
      Camera *camera = data;
      int image_no, ret, msglen, buflen;
      unsigned char  *msg, *buf;
      unsigned int retcode;

      image_no = gp_filesystem_number(fs, folder, filename, context);
      if(image_no < 0)
            return image_no;
      ret = hp_gen_cmd_1_16 (DELETE_PHOTO, image_no+1, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      free (msg);
      return (GP_OK);
}

static int
delete_all_func (CameraFilesystem *fs, const char *folder, void *data,
             GPContext *context)
{
      Camera *camera = data;
      unsigned char *buf;
      unsigned char *msg;
      unsigned int retcode;
      int      ret, buflen, msglen;

      ret = hp_gen_cmd_1_16 (DELETE_PHOTO, 0xFFFF, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      free (msg);
      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         ret, msglen, buflen, /* offset = 13, */ image_no;
      unsigned int      val, retcode;
      unsigned char     *xmsg, *msg, *buf;

      gp_log (GP_LOG_DEBUG, "hp215", "folder %s, filename %s", folder, filename);

      image_no = gp_filesystem_number(fs, folder, filename, context);
      if(image_no < 0)
            return image_no;
      ret = hp_gen_cmd_1_16 (GET_PHOTO_INFO, image_no+1, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      if (msglen < 2)
            return GP_ERROR_IO;

/*
0000  80 80 80 85 86 85-84 84 30 31 2f 30 32 2f  ..........01/02/
0010  30 30 20 31 34 3a 34 38-00 80 81 80 80 80 80 81  00 14:48........
0020  88 89 84 81 80 80 80 80-80 81 00 00 00 00 00 00  ................
0030  00 00 00 00 00 00      -                         ......          
 */
      xmsg = msg;
      ret = decode_u32(&xmsg, &msglen, &val);
      if (ret < GP_OK)
            return ret;
      memset (info, 0, sizeof(*info));
      info->file.fields = GP_FILE_INFO_SIZE;
      info->file.size = val;

      xmsg  += 0x0f;
      msglen      -= 0x0f;
      gp_log (GP_LOG_DEBUG, "hp215", "byte0 %02x", xmsg[0]);
      gp_log (GP_LOG_DEBUG, "hp215", "byte1 %02x", xmsg[1]);
      xmsg  += 2;
      msglen      -= 2;

      ret = decode_u32(&xmsg, &msglen, &val);
      if (ret < GP_OK)
            return ret;
      info->preview.fields = GP_FILE_INFO_SIZE;
      info->preview.size = val;

      gp_log (GP_LOG_DEBUG, "hp215", "byte2 %02x", xmsg[0]);
      gp_log (GP_LOG_DEBUG, "hp215", "byte3 %02x", xmsg[1]);

      free (msg);
      return GP_OK;
#if 0
      strcpy ((camera->pic[cnt+1])->date_time, &msg[0x0d]);

      /* Calculate day,month, year, hour and minute of the photo */
      (camera->pic[cnt+1])->date.day   = (msg[3+offset]-48)*10 + (msg[4+offset]-48);
      (camera->pic[cnt+1])->date.month = (msg[0+offset]-48)*10 + (msg[1+offset]-48);
      (camera->pic[cnt+1])->date.year  = 2000 + (msg[6+offset]-48)*10 + (msg[7+offset]-48);
      (camera->pic[cnt+1])->date.hour  = (msg[ 9+offset]-48)*10 + (msg[10+offset]-48);
      (camera->pic[cnt+1])->date.min   = (msg[12+offset]-48)*10 + (msg[13+offset]-48);

      /* Get the file info here and write it into <info> */

      return (GP_OK);
#endif
}

static int
file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
            void *data, GPContext *context)
{
      Camera            *camera = data;
      int         ret, msglen, buflen;
      unsigned int      retcode, count;
      unsigned char     *xmsg, *msg, *buf;

      /* Note: The original windows driver sends 0x348, and 4 bytes junk.
       * we just send the 0x348 and it works. */
      ret = hp_gen_cmd_1_16 (GET_ALBUM_INFO, 0x348, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      gp_log (GP_LOG_DEBUG, "hp215", "Sending photo album request ... ");
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      xmsg  = msg + 0x20; /* skip 0x20 byte string */
      msglen      = msglen - 0x20;
      ret = decode_u32(&xmsg, &msglen, &count);
      free (msg);
      if (ret < GP_OK)
            return ret;
      return gp_list_populate(list, "image%i.jpg", count);
}

#if 0 /* This function is not used by anybody */
static int
get_shoot_mode_table (Camera *camera) {
      unsigned char *buf, *msg, *xmsg;
      int ret, buflen, msglen;
      unsigned int i, cnt, val1, val2, val3, retcode;

      ret = hp_gen_cmd_blob (GET_SHOOT_MODE_TABLE, 0, NULL, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      gp_port_set_timeout (camera->port, 10000);
      free (buf);
      if (ret < GP_OK)
            return ret;
      if (retcode != HP215_OK) {
            free (msg);
            return GP_ERROR_BAD_PARAMETERS;
      }
      xmsg = msg;
      ret = decode_u32(&xmsg, &msglen, &val1);
      if (ret < GP_OK) return ret;
      ret = decode_u32(&xmsg, &msglen, &val2);
      if (ret < GP_OK) return ret;
      ret = decode_u32(&xmsg, &msglen, &val3);
      if (ret < GP_OK) return ret;
      
      gp_log (GP_LOG_DEBUG, "hp215", "shootmode table 0x%08x, 0x%08x, 0x%08x", val1, val2, val3);

      cnt = val1+val2;
      for (i=0;i<cnt;i++) {
            unsigned short val;
            /* 0x35 byte every loop */
            /* 0x20 byte string */
            gp_log (GP_LOG_DEBUG , "hp215", "%d: %s", i, xmsg);
            xmsg += 0x20;
            msglen -= 0x20;
            /* 0x15 left */
            /* u4 u4 u8 u7 u4 u4 u4 u4 u4 u4 */
            gp_log (GP_LOG_DEBUG, "hp215", "%01x %01x %02x %02x %01x %01x %01x %01x %01x %01x",
                  xmsg[0] & 0x0f,
                  xmsg[1] & 0x0f,
                  ((xmsg[2] & 0xf) << 4) | (xmsg[3] & 0xf),
                  xmsg[4] & 0x7f,
                  xmsg[5] & 0x0f,
                  xmsg[6] & 0x0f,
                  xmsg[7] & 0x0f,
                  xmsg[8] & 0x0f,
                  xmsg[9] & 0x0f,
                  xmsg[10] & 0x0f
            );
            /* u7 u7 u8 u7 u7 u16 */
            gp_log (GP_LOG_DEBUG, "hp215", "%02x %02x %02x %02x %02x",
                  xmsg[11] & 0x7f,
                  xmsg[12] & 0x7f,
                  ((xmsg[13] & 0xf) << 4) | (xmsg[14] & 0xf),
                  xmsg[15] & 0x7f,
                  xmsg[16] & 0x7f
            );
            xmsg += 0x11;
            msglen -= 0x11;
            decode_u16 (&xmsg, &msglen, &val);
            gp_log (GP_LOG_DEBUG, "hp215", "%04x", val);
      }

      free (msg);
      return GP_OK;
}
#endif

static int
camera_capture_preview (Camera *camera, CameraFile *file, GPContext *context)
{
      unsigned char *buf, *msg;
      int ret, buflen, msglen;
      unsigned int retcode;

      /* there is one mode where we send a 16bit 0x1 */
      ret = hp_gen_cmd_blob (TAKE_PREVIEW, 0, NULL, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      gp_port_set_timeout (camera->port, 10000);
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      if (retcode != HP215_OK) {
            free (msg);
            return GP_ERROR_BAD_PARAMETERS;
      }
      gp_file_set_mime_type (file, GP_MIME_JPEG);
      gp_file_set_data_and_size (file, (char*)msg, msglen);
      /* do not free (msg), we handed it to the lower layer right now */
      return ret;
}


static int
camera_capture (Camera *camera, CameraCaptureType type, CameraFilePath *path,
            GPContext *context)
{
      unsigned char *buf, *msg;
      int ret, buflen, msglen;
      unsigned int retcode;

/*    get_shoot_mode_table (camera); */

      /*ret = hp_gen_cmd_1_16 (TAKE_PHOTO, 1, &buf, &buflen);*/ /* download after capture */
      gp_port_set_timeout (camera->port, 60000);
      ret = hp_gen_cmd_blob (TAKE_PHOTO, 0, NULL, &buf, &buflen); /* store on camera */
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      gp_port_set_timeout (camera->port, 10000);
      free (buf);
      if (ret < GP_OK)
            return ret;
      free (msg);
      /*
       * tell libgphoto2 where to find it by filling out the path.
       */
      return GP_OK;
}


int
camera_id (CameraText *id) {
      strcpy(id->text, "hp215");
      return (GP_OK);
}


int
camera_abilities (CameraAbilitiesList *list) {
      CameraAbilities a;

      memset(&a, 0, sizeof(a));
      strcpy(a.model, "HP:PhotoSmart 215");
      a.status          = GP_DRIVER_STATUS_EXPERIMENTAL;
      a.port                  = GP_PORT_USB;
      a.usb_vendor            = 0x3f0;    /* HP */
      a.usb_product           = 0x6202;   /* Photosmart 215 */
      a.operations            = GP_OPERATION_CAPTURE_PREVIEW | GP_OPERATION_CAPTURE_IMAGE;
      a.file_operations = GP_FILE_OPERATION_DELETE | GP_FILE_OPERATION_PREVIEW;
      a.folder_operations     = GP_FOLDER_OPERATION_DELETE_ALL;
      return gp_abilities_list_append(list, a);
}

static CameraFilesystemFuncs fsfuncs = {
      .file_list_func = file_list_func,
      .get_info_func = get_info_func,
      .get_file_func = get_file_func,
      .del_file_func = delete_file_func,
      .delete_all_func = delete_all_func
};

int
camera_init (Camera *camera, GPContext *context)
{
      unsigned char *msg,*buf;
      int ret, msglen, buflen;
      unsigned int retcode;
      GPPortSettings settings;

      camera->functions->summary              = camera_summary;
      camera->functions->about                = camera_about;
      camera->functions->capture              = camera_capture;
      camera->functions->capture_preview      = camera_capture_preview;

      gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);

      gp_port_get_settings (camera->port, &settings);
      settings.usb.inep  = 0x83;
      settings.usb.outep = 0x04;
      gp_port_set_settings (camera->port, settings);
      /* This function does the initialisation sequence.
       * CMD = 0xce, REPLY = 2 byte, 0xe0 0xe0  ... apparently means ok.
       */
      gp_log (GP_LOG_DEBUG, "hp215", "Sending init sequence ... ");
      ret = hp_gen_cmd_blob (GET_CAMERA_READY, 0, NULL, &buf, &buflen);
      if (ret < GP_OK)
            return ret;
      ret = hp_send_command_and_receive_blob (camera, buf, buflen, &msg, &msglen, &retcode);
      free (buf);
      if (ret < GP_OK)
            return ret;
      free (msg);
      if (retcode != HP215_OK)
            return GP_ERROR_IO;
      return ret;
}

Generated by  Doxygen 1.6.0   Back to index