1 /* qm150.c
2 *
3 * Copyright 2003 Marcus Meissner <marcus@jet.franken.de>
4 * Aurelien Croc (AP2C) <programming@ap2c.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
20 *
21 * Modified by Aur�lien Croc (AP�C) <programming@ap2c.com>
22 * In particular : fix some bugs, and implementation of advanced
23 * functions : delete some images, delete all images, capture new image,
24 * update an image to the camera, get thumbnails, get information, get
25 * summary, get configuration, get manual, get about, get EXIF informations
26 *
27 */
28
29 /* NOTES :
30 * Becareful, image information number starts at 1 and finish at the
31 * max image number. But when you want to work on the images, you must
32 * read image informations, and check the real image number in the image
33 * information header and use this number with all functions !!
34 */
35
36 #define _DEFAULT_SOURCE
37
38 #include "config.h"
39
40 #include <string.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <gphoto2/gphoto2-library.h>
44 #include <gphoto2/gphoto2-result.h>
45 #include <gphoto2/gphoto2-port-log.h>
46
47 #ifdef HAVE_LIBEXIF
48 # include <libexif/exif-data.h>
49 # include <libexif/exif-utils.h>
50 #endif
51
52
53 #ifdef ENABLE_NLS
54 # include <libintl.h>
55 # undef _
56 # define _(String) dgettext (GETTEXT_PACKAGE, String)
57 # ifdef gettext_noop
58 # define N_(String) gettext_noop (String)
59 # else
60 # define N_(String) (String)
61 # endif
62 #else
63 # define _(String) (String)
64 # define N_(String) (String)
65 #endif
66
67 /* Functions codes */
68 #define CAPTUREIMAGE_CMD2 0x30
69 #define SETSPEED 0x42
70 #define ERASEIMAGE_CMD1 0x45
71 #define IMAGE_CMD2 0x46
72 #define GETIMAGE_CMD1 0x47
73 #define GETIMAGEINFO 0x49
74 #define CAPTUREIMAGE_CMD1 0x52
75 #define GETCAMINFO 0x53
76 #define GETTHUMBNAIL_CMD1 0x54
77 #define UPLOADDATA 0x55
78 #define PING 0x58
79
80 /* Return codes */
81 #define ESC 0x1b
82 #define ACK 0x06
83 #define NACK 0x15
84 #define NEXTFRAME 0x01
85 #define EOT 0x04
86
87 /* Data section pointers */
88 #define REC_MODE 0x01
89 #define IMAGE_PROTECTED 0x01
90
91 #define GP_MODULE "Konica"
92 #define FILENAME "image%04d.jpg"
93 #define IMAGE_WIDTH 1360
94 #define IMAGE_HEIGHT 1024
95 #define PREVIEW_WIDTH 160
96 #define PREVIEW_HEIGHT 120
97 #define FILENAME_LEN 1024+128
98
99 #define ACK_LEN 1
100 #define STATE_LEN 1
101 #define CSUM_LEN 1
102 #define INFO_BUFFER 256
103 #define DATA_BUFFER 512
104
105 /* Image information pointers */
106 #define PREVIEW_SIZE_PTR 0x4
107 #define IMAGE_SIZE_PTR 0x8
108 #define IMAGE_NUMBER 0xE
109 #define IMAGE_PROTECTION_FLAG 0x11
110
111 /* Camera information pointers */
112 #define CAPACITY_PTR 0x3
113 #define POWER_STATE_PTR 0x7
114 #define AUTO_OFF_PTR 0x8
115 #define CAMERA_MODE_PTR 0xA
116 #define LCD_STATE_PTR 0xB
117 #define ICON_STATE_PTR 0xC
118 #define FLASH_STATE_PTR 0xD
119 #define TIMER_PTR 0xE
120 #define RESOLUTION_PTR 0xF
121 #define WHITE_BALANCE_PTR 0x10
122 #define EXPOSURE_TIME_PTR 0x11
123 #define TAKEN_IMAGE_PTR 0x12
124 #define FREE_IMAGE_PTR 0x14
125 #define SHARPNESS_PTR 0x16
126 #define COLOR_PTR 0x17
127 #define RED_EYE_STATE_PTR 0x18
128 #define FOCUS_PTR 0x19
129 #define MACRO_PTR 0x1A
130 #define ZOOM_PTR 0x1B
131 #define CAPTURE_TYPE_PTR 0x1E
132 #define REC_DATE_DISP_PTR 0x1F
133 #define PLAY_DATE_DISP_PTR 0x20
134 #define DATE_FORMAT_PTR 0x21
135 #define TIMESTAMP_PTR 0x22
136
137 /** Local functions **********************************************************/
138
139 /*
140 * Check the integrity of datas
141 */
142 static unsigned char
k_calculate_checksum(unsigned char * buf,unsigned long int len)143 k_calculate_checksum (unsigned char *buf, unsigned long int len)
144 {
145 unsigned int i;
146 unsigned char result=0;
147 for (i=0; i < len; i++)
148 result += buf[i];
149 return result;
150 }
151
152 /*
153 * Check the connection and the camera
154 */
155 static int
k_ping(GPPort * port)156 k_ping (GPPort *port) {
157 char cmd[2], buf[1];
158 int ret;
159
160 cmd[0] = ESC;
161 cmd[1] = PING;
162 ret = gp_port_write (port, cmd, 2);
163 if (ret<GP_OK) return ret;
164 ret = gp_port_read (port, buf, 1);
165 if (ret<GP_OK) return ret;
166 if (buf[0] != ACK) return GP_ERROR;
167 return GP_OK;
168 }
169
170 /*
171 * Read image informations
172 */
173 static int
k_info_img(unsigned int image_no,void * data,CameraFileInfo * info,int * data_number)174 k_info_img (unsigned int image_no, void *data, CameraFileInfo* info,
175 int *data_number)
176 {
177 unsigned char cmd[6], buf[INFO_BUFFER];
178 Camera *camera = data;
179 int ret;
180
181 /* Read file information */
182 cmd[0] = ESC;
183 cmd[1] = GETIMAGEINFO;
184 cmd[2] = 0x30 + ((image_no/1000)%10);
185 cmd[3] = 0x30 + ((image_no/100 )%10);
186 cmd[4] = 0x30 + ((image_no/10 )%10);
187 cmd[5] = 0x30 + ( image_no %10);
188 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
189 if (ret<GP_OK) return ret;
190 ret = gp_port_read (camera->port, (char*)buf, INFO_BUFFER);
191 if (ret<GP_OK) return ret;
192
193 /* Search the image data number into the memory */
194 if (data_number != NULL)
195 *data_number = (buf[IMAGE_NUMBER] << 8)
196 | (buf[IMAGE_NUMBER+1]);
197
198 /* Get the file info here and write it into <info> */
199 /* There is no audio support with this camera */
200 info->audio.fields = GP_FILE_INFO_NONE;
201 /* Preview informations */
202 info->preview.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_SIZE
203 | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT;
204 strcpy (info->preview.type, GP_MIME_JPEG);
205 info->preview.size = ((buf[PREVIEW_SIZE_PTR] << 24) |
206 (buf[PREVIEW_SIZE_PTR+1] << 16) | (buf[PREVIEW_SIZE_PTR+2] << 8)
207 | buf[PREVIEW_SIZE_PTR+3]);
208 info->preview.width = PREVIEW_WIDTH;
209 info->preview.height = PREVIEW_HEIGHT;
210
211 /* Image information */
212 info->file.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_SIZE
213 | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT
214 | GP_FILE_INFO_PERMISSIONS;
215 strcpy (info->file.type, GP_MIME_JPEG);
216 info->file.size = ((buf[IMAGE_SIZE_PTR] << 24) |
217 (buf[IMAGE_SIZE_PTR+1] << 16) | (buf[IMAGE_SIZE_PTR+2] << 8)
218 | buf[IMAGE_SIZE_PTR+3]);
219 info->file.width = IMAGE_WIDTH;
220 info->file.height = IMAGE_HEIGHT;
221 if (buf[IMAGE_PROTECTION_FLAG] == IMAGE_PROTECTED)
222 info->file.permissions = GP_FILE_PERM_READ;
223 else
224 info->file.permissions = GP_FILE_PERM_ALL;
225 return (GP_OK);
226 }
227
228 /*
229 * Get data from the camera
230 * type = GP_FILE_TYPE_NORMAL, GP_FILE_TYPE_PREVIEW or GP_FILE_TYPE_EXIF
231 */
232 static int
k_getdata(int image_no,int type,unsigned int len,void * data,unsigned char * d,GPContext * context)233 k_getdata (int image_no, int type, unsigned int len, void *data,
234 unsigned char *d, GPContext *context)
235 {
236 Camera *camera = data;
237 unsigned char ack,state, cmd[7], buf[DATA_BUFFER], *buffer=d;
238 unsigned int id=0, bytes_read=0, i;
239 int ret;
240
241 cmd[0] = ESC;
242 cmd[1] = GETIMAGE_CMD1;
243 if (type != GP_FILE_TYPE_NORMAL)
244 cmd[1] = GETTHUMBNAIL_CMD1;
245 cmd[2] = IMAGE_CMD2;
246 cmd[3] = 0x30 + ((image_no/1000)%10);
247 cmd[4] = 0x30 + ((image_no/100 )%10);
248 cmd[5] = 0x30 + ((image_no/10 )%10);
249 cmd[6] = 0x30 + ( image_no %10);
250
251 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
252 if (ret<GP_OK) return ret;
253 ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
254 if (ret < GP_OK) return ret;
255 if (ack == NACK) {
256 gp_context_error(context, _("This preview doesn't exist."));
257 return (GP_ERROR);
258 }
259
260 /* Download the required image */
261 if (type == GP_FILE_TYPE_NORMAL)
262 id = gp_context_progress_start (context, len,
263 _("Downloading image..."));
264 for (i=0; i <= (len+DATA_BUFFER-1)/DATA_BUFFER ; i++) {
265 unsigned char csum;
266 int xret;
267
268 xret = gp_port_read (camera->port, (char*)buf, DATA_BUFFER);
269 if (xret < GP_OK) {
270 if (type == GP_FILE_TYPE_NORMAL)
271 gp_context_progress_stop (context, id);
272 return xret;
273 }
274 ret = gp_port_read (camera->port, (char*)&csum, CSUM_LEN);
275 if (ret < GP_OK) {
276 if (type == GP_FILE_TYPE_NORMAL)
277 gp_context_progress_stop (context, id);
278 return ret;
279 }
280 if ((k_calculate_checksum(buf, DATA_BUFFER)) != csum) {
281 if (type == GP_FILE_TYPE_NORMAL)
282 gp_context_progress_stop (context, id);
283 /* acknowledge the packet */
284 ack = NACK;
285 ret = gp_port_write (camera->port, (char*)&ack, ACK_LEN);
286 if (ret < GP_OK)
287 return ret;
288 gp_context_error(context, _("Data has been corrupted."));
289 return (GP_ERROR_CORRUPTED_DATA);
290 }
291 if ((len - bytes_read) > DATA_BUFFER) {
292 memcpy((char *)buffer, buf, xret);
293 buffer += DATA_BUFFER;
294 } else {
295 memcpy((char *)buffer, buf, (len - bytes_read));
296 buffer += len - bytes_read;
297 }
298
299 /* acknowledge the packet */
300 ack = ACK;
301 ret = gp_port_write (camera->port, (char*)&ack, ACK_LEN);
302 if (ret < GP_OK) {
303 if (type == GP_FILE_TYPE_NORMAL)
304 gp_context_progress_stop (context, id);
305 return ret;
306 }
307 ret = gp_port_read (camera->port, (char*)&state, STATE_LEN);
308 if (ret < GP_OK) {
309 if (type == GP_FILE_TYPE_NORMAL)
310 gp_context_progress_stop (context, id);
311 return ret;
312 }
313 if (state == EOT)
314 break;
315 bytes_read += DATA_BUFFER;
316 if (type == GP_FILE_TYPE_NORMAL)
317 gp_context_progress_update (context, id, bytes_read);
318 }
319 /* acknowledge the packet */
320 ack = ACK;
321 ret = gp_port_write (camera->port, (char*)&ack, ACK_LEN);
322 if (ret < GP_OK) {
323 if (type == GP_FILE_TYPE_NORMAL)
324 gp_context_progress_stop (context, id);
325 return ret;
326 }
327 if (type == GP_FILE_TYPE_NORMAL)
328 gp_context_progress_stop (context, id);
329 return (GP_OK);
330 }
331
332
333 /** Get and delete files *****************************************************/
334
335 /*
336 * Get images, thumbnails or EXIF datas
337 */
338 static int
get_file_func(CameraFilesystem * fs,const char * folder,const char * filename,CameraFileType type,CameraFile * file,void * data,GPContext * context)339 get_file_func (CameraFilesystem *fs, const char *folder, const char *filename,
340 CameraFileType type, CameraFile *file, void *data,
341 GPContext *context)
342 {
343 unsigned char *d;
344 int image_number, image_no, len, ret;
345 CameraFileInfo file_info;
346 #ifdef HAVE_LIBEXIF
347 ExifData *ed;
348 #endif
349
350 GP_DEBUG ("*** ENTER: get_file_func ***");
351
352 image_no = gp_filesystem_number(fs, folder, filename, context);
353 if (image_no < 0) return image_no;
354
355 /* Search the image informations */
356 image_no++;
357 ret = k_info_img (image_no, data, (CameraFileInfo *)&file_info,
358 &image_number);
359 image_no = image_number;
360 if (ret < GP_OK)
361 return ret;
362
363 switch (type) {
364 case GP_FILE_TYPE_NORMAL:
365 len = file_info.file.size;
366 if (!(d = (unsigned char *)malloc(len)))
367 return (GP_ERROR_NO_MEMORY);
368 ret = k_getdata(image_no, GP_FILE_TYPE_NORMAL,len,
369 data, d, context);
370 if (ret < GP_OK) {
371 free(d);
372 return ret;
373 }
374 break;
375 case GP_FILE_TYPE_PREVIEW:
376 len = file_info.preview.size;
377 if (!(d = (unsigned char *)malloc(len)))
378 return (GP_ERROR_NO_MEMORY);
379 ret = k_getdata(image_no, GP_FILE_TYPE_PREVIEW, len,
380 data, d, context);
381 if (ret < GP_OK) {
382 free(d);
383 return ret;
384 }
385 #ifdef HAVE_LIBEXIF
386 ed = exif_data_new_from_data ((unsigned char*)d, len);
387 if (ed->data) {
388 gp_file_set_mime_type (file, GP_MIME_JPEG);
389 ret = gp_file_append(file, (char*)ed->data, ed->size);
390 exif_data_unref (ed);
391 free (d);
392 return GP_OK;
393 }
394 exif_data_unref (ed);
395 free(d);
396 return GP_ERROR_NOT_SUPPORTED;
397 #else
398 gp_context_error(context, _("Compiled without EXIF support, no thumbnails available."));
399 free(d);
400 return GP_ERROR_NOT_SUPPORTED;
401 #endif
402 case GP_FILE_TYPE_EXIF:
403 len = file_info.preview.size;
404 if (!(d = (unsigned char *)malloc(len)))
405 return (GP_ERROR_NO_MEMORY);
406 ret = k_getdata(image_no, GP_FILE_TYPE_EXIF, len,
407 data, d, context);
408 if (ret < GP_OK) {
409 free(d);
410 return ret;
411 }
412 break;
413 default:
414 gp_context_error(context,
415 _("Image type %d is not supported by this camera !"), type);
416 return (GP_ERROR_NOT_SUPPORTED);
417 }
418 gp_file_set_mime_type (file, GP_MIME_JPEG);
419 ret = gp_file_append(file, (char*)d, len);
420 free(d);
421 return (ret);
422 }
423
424 /*
425 * Delete one image
426 * The image mustn't be protected
427 */
428 static int
delete_file_func(CameraFilesystem * fs,const char * folder,const char * filename,void * data,GPContext * context)429 delete_file_func (CameraFilesystem *fs, const char *folder,
430 const char *filename, void *data, GPContext *context)
431 {
432 Camera *camera = data;
433 CameraFileInfo file_info;
434 unsigned char cmd[7], ack;
435 int image_no;
436 int ret;
437
438 GP_DEBUG ("*** ENTER: delete_file_func ***");
439
440 image_no = gp_filesystem_number(fs, folder, filename, context);
441 if (image_no < 0) return image_no;
442
443 image_no++;
444 ret = k_info_img (image_no, data, (CameraFileInfo *)&file_info,
445 &image_no);
446 if (ret < GP_OK)
447 return ret;
448
449 /* Now, check if the image isn't protected */
450 if (file_info.file.permissions == GP_FILE_PERM_READ) {
451 gp_context_error(context, _("Image %s is delete protected."),
452 filename);
453 return (GP_ERROR);
454 }
455
456 /* Erase the image */
457 cmd[0] = ESC;
458 cmd[1] = ERASEIMAGE_CMD1;
459 cmd[2] = IMAGE_CMD2;
460 cmd[3] = 0x30 + ((image_no/1000)%10);
461 cmd[4] = 0x30 + ((image_no/100 )%10);
462 cmd[5] = 0x30 + ((image_no/10 )%10);
463 cmd[6] = 0x30 + ( image_no %10);
464 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
465 if (ret<GP_OK) return ret;
466 ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
467 if (ret<GP_OK) return ret;
468 if (ack != ACK) {
469 gp_context_error(context, _("Can't delete image %s."),filename);
470 return (GP_ERROR);
471 }
472 return (GP_OK);
473 }
474
475 /*
476 * Delete all images
477 */
478 static int
delete_all_func(CameraFilesystem * fs,const char * folder,void * data,GPContext * context)479 delete_all_func (CameraFilesystem *fs, const char *folder, void *data,
480 GPContext *context)
481 {
482 unsigned char cmd[7], ack;
483 int ret;
484 Camera *camera = data;
485
486 GP_DEBUG ("*** ENTER: delete_all_func ***");
487
488 cmd[0] = ESC;
489 cmd[1] = ERASEIMAGE_CMD1;
490 cmd[2] = IMAGE_CMD2;
491 cmd[3] = 0x30;
492 cmd[4] = 0x30;
493 cmd[5] = 0x30;
494 cmd[6] = 0x30;
495 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
496 if (ret<GP_OK) return ret;
497 ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
498 if (ret<GP_OK) return ret;
499 if (ack != ACK) {
500 gp_context_error(context, _("Can't delete all images."));
501 return (GP_ERROR);
502 }
503 return (GP_OK);
504 }
505
506
507 /** Additional functions to handle images ************************************/
508
509 /*
510 * Upload an image to the camera
511 */
512 static int
put_file_func(CameraFilesystem * fs,const char * folder,const char * name,CameraFileType type,CameraFile * file,void * data,GPContext * context)513 put_file_func (CameraFilesystem *fs, const char *folder, const char *name,
514 CameraFileType type, CameraFile *file,
515 void *data, GPContext *context)
516 {
517 Camera *camera = data;
518 unsigned char cmd[2], buf[DATA_BUFFER],ack,sum,state;
519 const char *d;
520 unsigned long int len, len_sent=0;
521 unsigned int id;
522 int ret;
523 unsigned int i;
524
525 GP_DEBUG ("*** ENTER: put_file_func ***");
526
527 /* Send function */
528 cmd[0] = ESC;
529 cmd[1] = UPLOADDATA;
530 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
531 if (ret<GP_OK)
532 return ret;
533 gp_file_get_data_and_size(file, &d, &len);
534 id = gp_context_progress_start (context, len, _("Uploading image..."));
535 for (i=0; i < ((len+DATA_BUFFER-1) / DATA_BUFFER); i++) {
536 ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
537 if (ret<GP_OK) {
538 gp_context_progress_stop (context, id);
539 return ret;
540 }
541 if (ack != ACK) {
542 gp_context_progress_stop (context, id);
543 gp_context_error(context,
544 _("Can't upload this image to the camera. "
545 "An error has occurred."));
546 return (GP_ERROR);
547 }
548 state = NEXTFRAME;
549 ret = gp_port_write (camera->port, (char*)&state, STATE_LEN);
550 if (ret<GP_OK) {
551 gp_context_progress_stop (context, id);
552 return ret;
553 }
554 if ((len - len_sent) <= DATA_BUFFER) {
555 /* Send the last datas */
556 ret = gp_port_write (camera->port, (char*)&d[i*DATA_BUFFER],
557 (len - len_sent));
558 if (ret<GP_OK) {
559 gp_context_progress_stop (context, id);
560 return ret;
561 }
562 /* and complete with zeros */
563 memset(buf,0,DATA_BUFFER);
564 ret = gp_port_write (camera->port, (char*)buf, (DATA_BUFFER -
565 (len - len_sent)));
566 if (ret<GP_OK) {
567 gp_context_progress_stop (context, id);
568 return ret;
569 }
570 /* Calculate the checksum */
571 sum = k_calculate_checksum(
572 (unsigned char *)&d[i*DATA_BUFFER],
573 (len-len_sent));
574 len_sent += (len - len_sent);
575 }
576 else {
577 /* Just send the datas */
578 ret = gp_port_write (camera->port, &d[i*DATA_BUFFER],
579 DATA_BUFFER);
580 if (ret<GP_OK) {
581 gp_context_progress_stop (context, id);
582 return ret;
583 }
584 len_sent += DATA_BUFFER;
585 sum = k_calculate_checksum(
586 (unsigned char *)&d[i*DATA_BUFFER],
587 DATA_BUFFER);
588 }
589 ret = gp_port_write (camera->port, (char*)&sum, CSUM_LEN);
590 if (ret<GP_OK) {
591 gp_context_progress_stop (context, id);
592 return ret;
593 }
594 gp_context_progress_update (context, id, len_sent);
595 }
596 state = EOT;
597 ret = gp_port_write (camera->port, (char*)&state, STATE_LEN);
598 if (ret<GP_OK) {
599 gp_context_progress_stop (context, id);
600 return ret;
601 }
602 ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
603 if (ret<GP_OK) {
604 gp_context_progress_stop (context, id);
605 return ret;
606 }
607 if (ack != ACK) {
608 gp_context_progress_stop (context, id);
609 gp_context_error(context, _("Can't upload this image to the "
610 "camera. An error has occurred."));
611 return (GP_ERROR);
612 }
613 gp_context_progress_stop (context, id);
614 return (GP_OK);
615 }
616
617 /*
618 * Capture an image
619 */
620 static int
camera_capture(Camera * camera,CameraCaptureType type,CameraFilePath * path,GPContext * context)621 camera_capture (Camera* camera, CameraCaptureType type, CameraFilePath* path,
622 GPContext *context)
623 {
624 unsigned char cmd[3], buf[256], ack;
625 int ret, nbr_images,images_taken,i;
626
627 GP_DEBUG ("*** ENTER: camera_capture ***");
628
629 /* Just check if there is space available yet */
630 cmd[0] = ESC;
631 cmd[1] = GETCAMINFO;
632 ret = gp_port_write (camera->port, (char*)cmd, 2);
633 if (ret<GP_OK)
634 return ret;
635 ret = gp_port_read (camera->port, (char*)buf, INFO_BUFFER);
636 nbr_images = (buf[FREE_IMAGE_PTR] << 8) | (buf[FREE_IMAGE_PTR+1]);
637 images_taken = (buf[TAKEN_IMAGE_PTR] << 8) | (buf[TAKEN_IMAGE_PTR+1]);
638
639 /* Capture the image */
640 cmd[0] = ESC;
641 cmd[1] = CAPTUREIMAGE_CMD1;
642 cmd[2] = CAPTUREIMAGE_CMD2;
643 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
644 if (ret<GP_OK)
645 return ret;
646 ret = gp_port_read (camera->port, (char*)&ack, ACK_LEN);
647 if (ret<GP_OK)
648 return ret;
649 if (ack == NACK) {
650 if (buf[CAMERA_MODE_PTR] != REC_MODE)
651 gp_context_error(context, _("You must be in record "
652 "mode to capture images."));
653 else if (!nbr_images)
654 gp_context_error(context, _("No space available "
655 "to capture new images. You must delete some "
656 "images."));
657 else
658 gp_context_error(context, _("Can't capture new images. "
659 "Unknown error"));
660 return (GP_ERROR);
661 }
662
663 /* Wait image writing in camera's memory */
664 for (i=0; i<=15; i++) {
665 sleep(1);
666 if ((ret = k_ping(camera->port)) == GP_OK)
667 break;
668 }
669 if (ret < GP_OK) {
670 gp_context_error(context, _("No answer from the camera."));
671 return (GP_ERROR);
672 }
673
674 /* Now register new image */
675 images_taken++;
676 sprintf (path->name, FILENAME, (unsigned int) images_taken);
677 return (GP_OK);
678 }
679
680 /*
681 * Get informations about an image
682 */
683 static int
get_info_func(CameraFilesystem * fs,const char * folder,const char * filename,CameraFileInfo * info,void * data,GPContext * context)684 get_info_func (CameraFilesystem *fs, const char *folder, const char *filename,
685 CameraFileInfo *info, void *data, GPContext *context)
686 {
687 int image_no;
688
689 GP_DEBUG ("*** ENTER: get_info_func ***");
690
691 image_no = gp_filesystem_number(fs, folder, filename, context);
692 if (image_no < 0)
693 return image_no;
694 image_no++;
695
696 return (k_info_img(image_no, data, info, NULL));
697 }
698
699
700 /** Driver base functions ****************************************************/
701
702 /*
703 * Create the image list
704 */
705 static int
file_list_func(CameraFilesystem * fs,const char * folder,CameraList * list,void * data,GPContext * context)706 file_list_func (CameraFilesystem *fs, const char *folder, CameraList *list,
707 void *data, GPContext *context)
708 {
709 Camera *camera = data;
710 unsigned char cmd[2], buf[INFO_BUFFER];
711 int num, ret;
712
713 GP_DEBUG ("*** ENTER: file_list_func ***");
714
715 cmd[0] = ESC;
716 cmd[1] = GETCAMINFO;
717 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
718 if (ret<GP_OK)
719 return ret;
720 ret = gp_port_read (camera->port, (char*)buf, INFO_BUFFER);
721 if (ret<GP_OK)
722 return ret;
723 num = (buf[TAKEN_IMAGE_PTR] << 8) | (buf[TAKEN_IMAGE_PTR+1]);
724 gp_list_populate (list, FILENAME, num);
725 return GP_OK;
726 }
727
728
729 /** Camera settings **********************************************************/
730 /*
731 * List all informations about the camera
732 */
733 static int
camera_get_config(Camera * camera,CameraWidget ** window,GPContext * context)734 camera_get_config (Camera* camera, CameraWidget** window, GPContext *context)
735 {
736 unsigned char cmd[2], buf[INFO_BUFFER];
737 int ret;
738 CameraWidget *widget;
739 CameraWidget *section;
740 time_t timestamp=0;
741 float value_float;
742
743 GP_DEBUG ("*** ENTER: camera_get_config ***");
744
745 /* get informations about camera */
746 cmd[0] = ESC;
747 cmd[1] = GETCAMINFO;
748 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
749 if (ret<GP_OK)
750 return ret;
751 ret = gp_port_read (camera->port, (char*)buf, INFO_BUFFER);
752 if (ret<GP_OK)
753 return ret;
754
755 /* Informations manipulation */
756 timestamp = (buf[TIMESTAMP_PTR] << 24) + (buf[TIMESTAMP_PTR+1] << 16)
757 + (buf[TIMESTAMP_PTR+2] << 8) + buf[TIMESTAMP_PTR+3];
758 /*
759 * This timestamp start the 1 January 1980 at 00:00
760 * but UNIX timestamp start the 1 January 1970 at 00:00
761 * so we calculate the UNIX timestamp with the camera's one
762 */
763 timestamp += (8*365 + 2*366)*24*3600-3600;
764
765 /* Window creation */
766 gp_widget_new (GP_WIDGET_WINDOW, _("Konica Configuration"), window);
767
768 /************************/
769 /* Persistent Settings */
770 /************************/
771 gp_widget_new (GP_WIDGET_SECTION, _("Persistent Settings"), §ion);
772 gp_widget_append (*window, section);
773
774 /* Date */
775 gp_widget_new (GP_WIDGET_DATE, _("Date and Time"), &widget);
776 gp_widget_append (section, widget);
777 gp_widget_set_value (widget, ×tamp);
778
779 /* Auto Off Time */
780 gp_widget_new (GP_WIDGET_RANGE, _("Auto Off Time"), &widget);
781 gp_widget_append (section, widget);
782 gp_widget_set_range (widget, 1, 255, 1);
783 value_float = ((buf[AUTO_OFF_PTR] << 8) + buf[AUTO_OFF_PTR+1]) / 60;
784 gp_widget_set_value (widget, &value_float);
785
786
787 /* Resolution */
788 gp_widget_new (GP_WIDGET_RADIO, _("Resolution"), &widget);
789 gp_widget_append (section, widget);
790 gp_widget_add_choice (widget, _("Low"));
791 gp_widget_add_choice (widget, _("Medium"));
792 gp_widget_add_choice (widget, _("High"));
793 switch (buf[RESOLUTION_PTR]) {
794 case 1:
795 gp_widget_set_value (widget, _("High"));
796 break;
797 case 2:
798 gp_widget_set_value (widget, _("Low"));
799 break;
800 case 0:
801 gp_widget_set_value (widget, _("Medium"));
802 break;
803 }
804
805 /* LCD */
806 gp_widget_new (GP_WIDGET_RADIO, _("LCD"), &widget);
807 gp_widget_append (section, widget);
808 gp_widget_add_choice (widget, _("On"));
809 gp_widget_add_choice (widget, _("Off"));
810 switch (buf[LCD_STATE_PTR]) {
811 case 0:
812 gp_widget_set_value (widget, _("On"));
813 break;
814 case 1:
815 gp_widget_set_value (widget, _("Off"));
816 break;
817 }
818
819 /* Icons */
820 gp_widget_new (GP_WIDGET_RADIO, _("Icons"), &widget);
821 gp_widget_append (section, widget);
822 gp_widget_add_choice (widget, _("On"));
823 gp_widget_add_choice (widget, _("Off"));
824 switch (buf[ICON_STATE_PTR]) {
825 case 0:
826 gp_widget_set_value (widget, _("On"));
827 break;
828 case 1:
829 gp_widget_set_value (widget, _("Off"));
830 break;
831 }
832
833 /****************/
834 /* Localization */
835 /****************/
836 gp_widget_new (GP_WIDGET_SECTION, _("Localization"), §ion);
837 gp_widget_append (*window, section);
838
839 /* Date format */
840 gp_widget_new (GP_WIDGET_MENU, _("Date Format"), &widget);
841 gp_widget_append (section, widget);
842 gp_widget_add_choice (widget, _("Month/Day/Year"));
843 gp_widget_add_choice (widget, _("Day/Month/Year"));
844 gp_widget_add_choice (widget, _("Year/Month/Day"));
845 switch (buf[DATE_FORMAT_PTR]) {
846 case 0:
847 gp_widget_set_value (widget, _("Month/Day/Year"));
848 break;
849 case 1:
850 gp_widget_set_value (widget, _("Day/Month/Year"));
851 break;
852 case 2:
853 gp_widget_set_value (widget, _("Year/Month/Day"));
854 break;
855 }
856
857 /********************************/
858 /* Session-persistent Settings */
859 /********************************/
860 gp_widget_new (GP_WIDGET_SECTION, _("Session-persistent Settings"),
861 §ion);
862 gp_widget_append (*window, section);
863
864 /* Flash */
865 gp_widget_new (GP_WIDGET_RADIO, _("Flash"), &widget);
866 gp_widget_append (section, widget);
867 gp_widget_add_choice (widget, _("Off"));
868 gp_widget_add_choice (widget, _("On"));
869 gp_widget_add_choice (widget, _("On, red-eye reduction"));
870 gp_widget_add_choice (widget, _("Auto"));
871 gp_widget_add_choice (widget, _("Auto, red-eye reduction"));
872 switch (buf[FLASH_STATE_PTR]) {
873 case 2:
874 gp_widget_set_value (widget, _("Off"));
875 break;
876 case 1:
877 if (buf[RED_EYE_STATE_PTR] == 1)
878 gp_widget_set_value (widget,
879 _("On, red-eye reduction"));
880 else
881 gp_widget_set_value (widget, _("On"));
882 break;
883 case 0:
884 if (buf[RED_EYE_STATE_PTR] == 1)
885 gp_widget_set_value (widget,
886 _("Auto, red-eye reduction"));
887 else
888 gp_widget_set_value (widget, _("Auto"));
889 break;
890 }
891
892 /* Exposure */
893 gp_widget_new (GP_WIDGET_RANGE, _("Exposure"), &widget);
894 gp_widget_append (section, widget);
895 gp_widget_set_range (widget, -2, 2, 0.1);
896 switch(buf[EXPOSURE_TIME_PTR]) {
897 case 0:
898 value_float = 0;
899 break;
900 case 1:
901 value_float = 0.3;
902 break;
903 case 2:
904 value_float = 0.5;
905 break;
906 case 3:
907 value_float = 0.8;
908 break;
909 case 4:
910 value_float = 1.0;
911 break;
912 case 5:
913 value_float = 1.3;
914 break;
915 case 6:
916 value_float = 1.5;
917 break;
918 case 7:
919 value_float = 1.8;
920 break;
921 case 8:
922 value_float = 2.0;
923 break;
924 case 0xF8:
925 value_float = -2.0;
926 break;
927 case 0xF9:
928 value_float = -1.8;
929 break;
930 case 0xFA:
931 value_float = -1.5;
932 break;
933 case 0xFB:
934 value_float = -1.3;
935 break;
936 case 0xFC:
937 value_float = -1.0;
938 break;
939 case 0xFD:
940 value_float = -0.8;
941 break;
942 case 0xFE:
943 value_float = -0.5;
944 break;
945 case 0xFF:
946 value_float = -0.3;
947 break;
948 }
949 gp_widget_set_value (widget, &value_float);
950
951 /* Focus */
952 gp_widget_new (GP_WIDGET_RADIO, _("Focus"), &widget);
953 gp_widget_append (section, widget);
954 gp_widget_add_choice (widget, _("2.0 m"));
955 gp_widget_add_choice (widget, _("0.5 m"));
956 gp_widget_add_choice (widget, _("0.1 m"));
957 gp_widget_add_choice (widget, _("Auto"));
958 switch (buf[FOCUS_PTR]) {
959 case 0:
960 gp_widget_set_value (widget, _("Auto"));
961 break;
962 case 1:
963 gp_widget_set_value (widget, _("2.0 m"));
964 break;
965 case 2:
966 gp_widget_set_value (widget, _("0.5 m"));
967 break;
968 case 3:
969 gp_widget_set_value (widget, _("0.1 m"));
970 break;
971 }
972
973 /* white balance */
974 gp_widget_new (GP_WIDGET_RADIO, _("White balance"), &widget);
975 gp_widget_append (section, widget);
976 gp_widget_add_choice (widget, _("Office"));
977 gp_widget_add_choice (widget, _("Daylight"));
978 gp_widget_add_choice (widget, _("Auto"));
979 switch (buf[WHITE_BALANCE_PTR]) {
980 case 0:
981 gp_widget_set_value (widget, _("Auto"));
982 break;
983 case 1:
984 gp_widget_set_value (widget, _("Daylight"));
985 break;
986 case 2:
987 gp_widget_set_value (widget, _("Office"));
988 break;
989 }
990
991 /* Sharpness */
992 gp_widget_new (GP_WIDGET_RADIO, _("Sharpness"), &widget);
993 gp_widget_append (section, widget);
994 gp_widget_add_choice (widget, _("Sharp"));
995 gp_widget_add_choice (widget, _("Soft"));
996 gp_widget_add_choice (widget, _("Auto"));
997 switch (buf[SHARPNESS_PTR]) {
998 case 0:
999 gp_widget_set_value (widget, _("Auto"));
1000 break;
1001 case 1:
1002 gp_widget_set_value (widget, _("Sharp"));
1003 break;
1004 case 2:
1005 gp_widget_set_value (widget, _("Soft"));
1006 break;
1007 }
1008
1009 /* Color */
1010 gp_widget_new (GP_WIDGET_RADIO, _("Color"), &widget);
1011 gp_widget_append (section, widget);
1012 gp_widget_add_choice (widget, _("Light"));
1013 gp_widget_add_choice (widget, _("Deep"));
1014 gp_widget_add_choice (widget, _("Black and White"));
1015 gp_widget_add_choice (widget, _("Sepia"));
1016 gp_widget_add_choice (widget, _("Auto"));
1017 switch (buf[COLOR_PTR]) {
1018 case 0:
1019 gp_widget_set_value (widget, _("Auto"));
1020 break;
1021 case 1:
1022 gp_widget_set_value (widget, _("Light"));
1023 break;
1024 case 2:
1025 gp_widget_set_value (widget, _("Deep"));
1026 break;
1027 case 3:
1028 gp_widget_set_value (widget, _("Black and White"));
1029 break;
1030 case 4:
1031 gp_widget_set_value (widget, _("Sepia"));
1032 break;
1033 }
1034
1035 /* Macro */
1036 gp_widget_new (GP_WIDGET_RADIO, _("Macro"), &widget);
1037 gp_widget_append (section, widget);
1038 gp_widget_add_choice (widget, _("On"));
1039 gp_widget_add_choice (widget, _("Off"));
1040 switch (buf[MACRO_PTR]) {
1041 case 0:
1042 gp_widget_set_value (widget, _("Off"));
1043 break;
1044 case 1:
1045 gp_widget_set_value (widget, _("On"));
1046 break;
1047 }
1048
1049 /* Zoom */
1050 gp_widget_new (GP_WIDGET_RADIO, _("Zoom"), &widget);
1051 gp_widget_append (section, widget);
1052 gp_widget_add_choice (widget, _("On"));
1053 gp_widget_add_choice (widget, _("Off"));
1054 switch (buf[ZOOM_PTR]) {
1055 case 0:
1056 gp_widget_set_value (widget, _("Off"));
1057 break;
1058 case 1:
1059 gp_widget_set_value (widget, _("On"));
1060 break;
1061 }
1062
1063 /* Capture */
1064 gp_widget_new (GP_WIDGET_RADIO, _("Capture"), &widget);
1065 gp_widget_append (section, widget);
1066 gp_widget_add_choice (widget, _("Single"));
1067 gp_widget_add_choice (widget, _("Sequence 9"));
1068 switch (buf[CAPTURE_TYPE_PTR]) {
1069 case 0:
1070 gp_widget_set_value (widget, _("Single"));
1071 break;
1072 case 1:
1073 gp_widget_set_value (widget, _("Sequence 9"));
1074 break;
1075 }
1076
1077 /* Date display */
1078 gp_widget_new (GP_WIDGET_RADIO, _("Date display"), &widget);
1079 gp_widget_append (section, widget);
1080 gp_widget_add_choice (widget, _("Anywhere"));
1081 gp_widget_add_choice (widget, _("Play mode"));
1082 gp_widget_add_choice (widget, _("Record mode"));
1083 gp_widget_add_choice (widget, _("Everywhere"));
1084 switch (buf[REC_DATE_DISP_PTR]) {
1085 case 0:
1086 if (buf[PLAY_DATE_DISP_PTR] == 0)
1087 gp_widget_set_value (widget, _("Play mode"));
1088 else
1089 gp_widget_set_value (widget, _("Anywhere"));
1090 break;
1091 case 1:
1092 if (buf[PLAY_DATE_DISP_PTR] == 0)
1093 gp_widget_set_value (widget, _("Everywhere"));
1094 else
1095 gp_widget_set_value (widget, _("Record mode"));
1096 break;
1097 }
1098
1099 /************************/
1100 /* Volatile Settings */
1101 /************************/
1102 gp_widget_new (GP_WIDGET_SECTION, _("Volatile Settings"), §ion);
1103 gp_widget_append (*window, section);
1104
1105 /* Self Timer */
1106 gp_widget_new (GP_WIDGET_RADIO, _("Self Timer"), &widget);
1107 gp_widget_append (section, widget);
1108 gp_widget_add_choice (widget, _("Self Timer (next picture only)"));
1109 gp_widget_add_choice (widget, _("Normal"));
1110 switch (buf[TIMER_PTR]) {
1111 case 1:
1112 gp_widget_set_value (widget, _("Self Timer ("
1113 "next picture only)"));
1114 break;
1115 case 0:
1116 gp_widget_set_value (widget, _("Normal"));
1117 break;
1118 }
1119 return (GP_OK);
1120 }
1121
1122 static int
camera_set_config(Camera * camera,CameraWidget * window,GPContext * context)1123 camera_set_config (Camera *camera, CameraWidget *window, GPContext *context)
1124 {
1125 /* Can't change configuration */
1126 return(GP_ERROR);
1127 }
1128
1129 static int
camera_summary(Camera * camera,CameraText * text,GPContext * context)1130 camera_summary (Camera *camera, CameraText *text, GPContext *context)
1131 {
1132 unsigned char cmd[2], buf[INFO_BUFFER];
1133 char date_disp[20],date[50];
1134 char power[20],mode[20];
1135 int ret,capacity=0,autopoweroff=0,image_taken=0,image_remained=0;
1136 time_t timestamp=0;
1137 struct tm tmp;
1138
1139 GP_DEBUG ("*** ENTER: camera_summary ***");
1140
1141 /* get informations about camera */
1142 cmd[0] = ESC;
1143 cmd[1] = GETCAMINFO;
1144 ret = gp_port_write (camera->port, (char*)cmd, sizeof(cmd));
1145 if (ret<GP_OK)
1146 return ret;
1147 ret = gp_port_read (camera->port, (char*)buf, INFO_BUFFER);
1148 if (ret<GP_OK)
1149 return ret;
1150
1151 capacity = buf[CAPACITY_PTR]*0x100 + buf[CAPACITY_PTR+1];
1152 snprintf(power,sizeof(power),_("Battery"));
1153 if (buf[POWER_STATE_PTR] == 1)
1154 snprintf(power,sizeof(power),_("AC"));
1155 autopoweroff = buf[AUTO_OFF_PTR]*0x100 + buf[AUTO_OFF_PTR+1];
1156 autopoweroff /= 60;
1157 snprintf(mode,sizeof(mode),_("Play"));
1158 if (buf[CAMERA_MODE_PTR] == 1)
1159 snprintf(mode,sizeof(mode),_("Record"));
1160 image_taken = buf[TAKEN_IMAGE_PTR] * 0x100 + buf[TAKEN_IMAGE_PTR+1];
1161 image_remained = buf[FREE_IMAGE_PTR] * 0x100 + buf[FREE_IMAGE_PTR+1];
1162
1163 timestamp = (buf[TIMESTAMP_PTR] << 24) + (buf[TIMESTAMP_PTR+1] << 16)
1164 + (buf[TIMESTAMP_PTR+2] << 8) + buf[TIMESTAMP_PTR+3];
1165 timestamp = (unsigned int)timestamp + (8*365 + 2*366)*24*3600-3600;
1166 tmp = *localtime(×tamp);
1167 switch (buf[DATE_FORMAT_PTR]) {
1168 case 1:
1169 snprintf(date_disp,sizeof(date_disp),_("DD/MM/YYYY"));
1170 strftime(date,sizeof(date),"%d/%m/%Y %H:%M",&tmp);
1171 break;
1172 case 2:
1173 strftime(date,sizeof(date),"%Y/%m/%d %H:%M",&tmp);
1174 snprintf(date_disp,sizeof(date_disp),_("YYYY/MM/DD"));
1175 break;
1176 default:
1177 strftime(date,sizeof(date),"%m/%d/%Y %H:%M",&tmp);
1178 snprintf(date_disp,sizeof(date_disp),_("MM/DD/YYYY"));
1179 break;
1180 }
1181 snprintf(text->text, sizeof(text->text),
1182 _("Model: %s\n"
1183 "Capacity: %i Mb\n"
1184 "Power: %s\n"
1185 "Auto Off Time: %i min\n"
1186 "Mode: %s\n"
1187 "Images: %i/%i\n"
1188 "Date display: %s\n"
1189 "Date and Time: %s\n"),
1190 "Konica Q-M150",capacity,
1191 power,autopoweroff,mode,
1192 image_taken,image_remained,
1193 date_disp,date);
1194 return (GP_OK);
1195 }
1196
1197 /** Camera's driver informations *********************************************/
1198
1199 /*
1200 * Say somethings about driver's authors
1201 */
1202 static int
camera_about(Camera * camera,CameraText * about,GPContext * context)1203 camera_about (Camera* camera, CameraText* about, GPContext *context)
1204 {
1205 snprintf(about->text,sizeof(about->text),_("Konica Q-M150 Library\n"
1206 "Marcus Meissner <marcus@jet.franken.de>\n"
1207 "Aurelien Croc (AP2C) <programming@ap2c.com>\n"
1208 "http://www.ap2c.com\n"
1209 "Support for the french Konica Q-M150."));
1210 return(GP_OK);
1211 }
1212
1213 /*
1214 * just say some things about this driver
1215 */
1216 static int
camera_manual(Camera * camera,CameraText * manual,GPContext * context)1217 camera_manual (Camera *camera, CameraText *manual, GPContext *context)
1218 {
1219 snprintf(manual->text,sizeof(manual->text),
1220 _("About Konica Q-M150:\n"
1221 "This camera does not allow any changes\n"
1222 "from the outside. So in the configuration, you can\n"
1223 "only see what it is configured on the camera\n"
1224 "but you can not change anything.\n\n"
1225 "If you have some issues with this driver, please e-mail its authors.\n"
1226 ));
1227 return (GP_OK);
1228 }
1229
1230 /*
1231 * Camera's identification
1232 */
1233 int
camera_id(CameraText * id)1234 camera_id (CameraText *id)
1235 {
1236 strcpy(id->text, "konica qm150");
1237 return (GP_OK);
1238 }
1239
1240 /*
1241 * List all camera's abilities
1242 */
1243 int
camera_abilities(CameraAbilitiesList * list)1244 camera_abilities (CameraAbilitiesList *list)
1245 {
1246 CameraAbilities a;
1247
1248 memset(&a, 0, sizeof(a));
1249 strcpy(a.model, "Konica:Q-M150");
1250 a.status = GP_DRIVER_STATUS_EXPERIMENTAL;
1251 a.port = GP_PORT_SERIAL;
1252 a.speed[0] = 115200;
1253 a.speed[1] = 0;
1254 a.operations = GP_OPERATION_CAPTURE_IMAGE |
1255 GP_OPERATION_CAPTURE_PREVIEW | GP_OPERATION_CONFIG;
1256 a.file_operations = GP_FILE_OPERATION_DELETE |
1257 GP_FILE_OPERATION_EXIF | GP_FILE_OPERATION_PREVIEW;
1258 a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL |
1259 GP_FOLDER_OPERATION_PUT_FILE;
1260 gp_abilities_list_append(list, a);
1261 return (GP_OK);
1262 }
1263
1264 /** Camera's initialization **************************************************/
1265 /*
1266 * Initialization of the camera
1267 */
1268
1269 static CameraFilesystemFuncs fsfuncs = {
1270 .file_list_func = file_list_func,
1271 .get_info_func = get_info_func,
1272 .get_file_func = get_file_func,
1273 .put_file_func = put_file_func,
1274 .del_file_func = delete_file_func,
1275 .delete_all_func = delete_all_func,
1276 };
1277 int
camera_init(Camera * camera,GPContext * context)1278 camera_init (Camera *camera, GPContext *context)
1279 {
1280 GPPortSettings settings;
1281 int speeds[] = { 115200, 9600, 19200, 38400, 57600, 115200 };
1282 int ret;
1283 unsigned int i;
1284 char cmd[3], buf[1];
1285
1286 /* First, set up all the function pointers. */
1287 camera->functions->capture = camera_capture;
1288 camera->functions->about = camera_about;
1289 camera->functions->get_config = camera_get_config;
1290 camera->functions->set_config = camera_set_config;
1291 camera->functions->summary = camera_summary;
1292 camera->functions->manual = camera_manual;
1293
1294
1295 /* Now, tell the filesystem where to get lists, files and info */
1296 gp_filesystem_set_funcs (camera->fs, &fsfuncs, camera);
1297
1298 /*
1299 * The port is already provided with camera->port (and
1300 * already open). You just have to use functions like
1301 * gp_port_timeout_set, gp_port_settings_get, gp_port_settings_set.
1302 */
1303 gp_port_get_settings (camera->port, &settings);
1304 settings.serial.speed = 115200;
1305 settings.serial.bits = 8;
1306 settings.serial.stopbits= 1;
1307 settings.serial.parity = 0;
1308 gp_port_set_settings (camera->port, settings);
1309 /*
1310 * Once you have configured the port, you should check if a
1311 * connection to the camera can be established.
1312 */
1313 for (i=0;i<sizeof(speeds)/sizeof(speeds[0]);i++) {
1314 gp_port_get_settings (camera->port, &settings);
1315 settings.serial.speed = speeds[i];
1316 gp_port_set_settings (camera->port, settings);
1317 if (GP_OK<=k_ping (camera->port))
1318 break;
1319 }
1320 if (i == sizeof(speeds)/sizeof(speeds[0]))
1321 return GP_ERROR;
1322 cmd[0] = ESC;
1323 cmd[1] = SETSPEED;
1324 cmd[2] = 0x30 + 4; /* speed nr 4:(9600, 19200, 38400, 57600, 115200) */
1325 ret = gp_port_write (camera->port, cmd, 3);
1326 if (ret<GP_OK) return ret;
1327 ret = gp_port_read (camera->port, buf, 1);
1328 if (ret<GP_OK) return ret;
1329 if (buf[0] != ACK) return GP_ERROR;
1330 gp_port_get_settings (camera->port, &settings);
1331 settings.serial.speed = 115200;
1332 gp_port_set_settings (camera->port, settings);
1333 return GP_OK;
1334 }
1335