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"), &section);
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, &timestamp);
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"), &section);
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                        &section);
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"), &section);
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(&timestamp);
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