2 * Jenopt JD11 Camera Driver
3 * Copyright © 1999-2001 Marcus Meissner <marcus@jet.franken.de>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
28 #include <gphoto2/gphoto2.h>
29 #include <gphoto2/gphoto2-port.h>
39 # define _(String) dgettext (GETTEXT_PACKAGE, String)
41 # define N_(String) gettext_noop (String)
43 # define N_(String) (String)
46 # define textdomain(String) (String)
47 # define gettext(String) (String)
48 # define dgettext(Domain,Message) (Message)
49 # define dcgettext(Domain,Message,Type) (Message)
50 # define bindtextdomain(Domain,Directory) (Domain)
51 # define _(String) (String)
52 # define N_(String) (String)
57 dread(GPPort *port, caddr_t buf, int xsize) {
59 int ret = gp_port_read(port,buf,xsize);
65 fprintf(stderr,"dread[%d]:",ret);
66 for (i=0;i<ret;i++) fprintf(stderr,"%02x,",buf[i]);
71 dwrite(GPPort*port, caddr_t buf, int xsize) {
73 int ret = gp_port_write(port,buf,xsize);
79 fprintf(stderr,"dwrite[%d/%d]:",xsize,ret);
80 for (i=0;i<xsize;i++) fprintf(stderr,"%02x,",buf[i]);
86 #define READ(port,buf,len) gp_port_read(port,(char*)(buf),len)
87 #define WRITE(port,buf,len) gp_port_write(port,(char*)(buf),len)
89 static int _send_cmd(GPPort *port,unsigned short cmd) {
93 return WRITE(port,buf,2);
96 static int _read_cmd(GPPort *port,unsigned short *xcmd) {
101 if (1==(ret=READ(port,buf,1))) {
103 if (1==READ(port,buf+1,1)) {
104 *xcmd = (buf[0] << 8)| buf[1];
116 static void _dump_buf(unsigned char *buf,int size) {
120 fprintf(stderr,"%02x ",buf[i]);
121 fprintf(stderr,"]\n");
126 static int _send_cmd_2(GPPort *port,unsigned short cmd, unsigned short *xcmd) {
127 unsigned char buf[2];
134 ret = WRITE(port,buf,2);
136 if (1==(ret=READ(port,buf,1))) {
138 if (1==READ(port,buf+1,1)) {
139 *xcmd = (buf[0] << 8)| buf[1];
151 int jd11_ping(GPPort *port) {
158 while (1==READ(port,buf,1))
159 /* drain input queue before PING */;
160 ret=_send_cmd_2(port,0xff08,&xcmd);
161 if ((ret>=GP_OK) && (xcmd==0xfff1))
168 jd11_get_rgb(GPPort *port,float *red, float *green, float *blue) {
170 int ret=GP_OK,tries=0,curread=0;
172 _send_cmd(port,0xffa7);
173 while ((curread<10) && (tries++<30)) {
174 ret=READ(port,buf+curread,sizeof(buf)-curread);
182 fprintf(stderr,"%d returned bytes on float query.\n",ret);
185 /*_dump_buf(buf,10);*/
186 *green = buf[1]+buf[2]*0.1+buf[3]*0.01;
187 *red = buf[4]+buf[5]*0.1+buf[6]*0.01;
188 *blue = buf[7]+buf[8]*0.1+buf[9]*0.01;
193 jd11_set_rgb(GPPort *port,float red, float green, float blue) {
194 unsigned char buf[20];
196 _send_cmd(port,0xffa7);
199 buf[2] = ((int)(green*10))%10;
200 buf[3] = ((int)(green*100))%10;
202 buf[5] = ((int)(red*10))%10;
203 buf[6] = ((int)(red*100))%10;
205 buf[8] = ((int)(blue*10))%10;
206 buf[9] = ((int)(blue*100))%10;
207 /*_dump_buf(buf,10);*/
208 return WRITE(port,buf,10);
212 jd11_select_index(GPPort *port) { /* select index */
216 ret = _send_cmd_2(port,0xffa4,&xcmd);
225 jd11_select_image(GPPort *port,int nr) { /* select image <nr> */
228 _send_cmd(port,0xffa1);
229 _send_cmd(port,0xff00|nr);
230 _read_cmd(port,&xcmd);
237 jd11_set_bulb_exposure(GPPort *port,int i) {
241 return GP_ERROR_BAD_PARAMETERS;
243 _send_cmd(port,0xffa9);
244 _send_cmd(port,0xff00|i);
245 _read_cmd(port,&xcmd);
250 static void jd11_TestADC(GPPort *port) {
253 _send_cmd(port,0xff75);
254 _read_cmd(port,&xcmd);
255 fprintf(stderr,"TestADC: done, xcmd=%x\n",xcmd);
257 static void cmd_TestDRAM(GPPort *port) {
260 _send_cmd(port,0xff72);
261 _read_cmd(port,&xcmd);
262 fprintf(stderr,"TestDRAM: done.\n");
265 /* doesn't actually flash */
266 static void cmd_TestFLASH(GPPort *port) {
269 _send_cmd(port,0xff73);
270 _read_cmd(port,&xcmd);
271 fprintf(stderr,"TestFLASH: xcmd = %x.\n",xcmd);
274 /* some kind of selftest ... shuts the shutters, beeps... only stops by
276 static void cmd_79(GPPort *port) {
279 _send_cmd(port,0xff79);
280 _read_cmd(port,&xcmd);
281 fprintf(stderr,"79: done, xcmd =%x\n",xcmd);
287 jd11_imgsize(GPPort *port) {
292 _send_cmd(port,0xfff0);
294 ret=READ(port,&buf[curread],10-curread);
298 } while ((i++<20) && (curread<10));
299 /*_dump_buf(buf,curread);*/
300 if (!curread) /* We get 0 bytes return for 0 images. */
302 ret=strtol(&buf[2],NULL,16);
307 getpacket(GPPort *port,unsigned char *buf, int expect) {
308 int curread = 0, csum = 0;
316 ret=READ(port,buf+curread,expect-curread);
323 } while ((i++<2) && (curread<expect));
324 if (curread!=expect) {
327 _send_cmd(port,0xfff3);
331 /*printf("curread is %d\n",curread);*/
332 /*printf("PACKET:");_dump_buf(buf,curread);*/
333 for (i=0;i<curread-1;i++)
335 if (buf[curread-1]==(csum&0xff) || (curread!=201))
337 fprintf(stderr,"BAD CHECKSUM %x vs %x, trying resend...\n",buf[curread-1],csum&0xff);
338 _send_cmd(port,0xfff3);
340 /*return curread-1;*/
342 fprintf(stderr,"Giving up after 5 tries.\n");
347 jd11_erase_all(GPPort *port) {
348 return _send_cmd(port,0xffa6);
351 /* This function reads all thumbnails at once and initializes the whole
352 * camera filesystem. This can be done, because finding out how much
353 * pictures are on the camera is done by reading the whole preview picture
355 * And since the file infos are static mostly, why not just set them too at
359 jd11_index_reader(GPPort *port, CameraFilesystem *fs, GPContext *context) {
360 int i, id, count, xsize, curread=0, ret=0;
361 unsigned char *indexbuf;
363 ret = jd11_select_index(port);
366 xsize = jd11_imgsize(port);
367 if (!xsize) { /* shortcut, no reading needed */
370 count = xsize/(64*48);
371 xsize = count * (64*48);
372 indexbuf = malloc(xsize);
373 if (!indexbuf) return GP_ERROR_NO_MEMORY;
374 id = gp_context_progress_start (context, xsize,
375 _("Downloading thumbnail..."));
376 _send_cmd(port,0xfff1);
377 while (curread < xsize) {
378 int readsize = xsize-curread;
379 if (readsize>200) readsize = 200;
380 ret=getpacket(port,indexbuf+curread,readsize);
386 gp_context_progress_update (context, id, curread);
387 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
388 /* What to do...Just free the stuff we allocated for now.*/
390 return GP_ERROR_CANCEL;
392 _send_cmd(port,0xfff1);
394 gp_context_progress_stop (context, id);
395 for (i=0;i<count;i++) {
399 unsigned char thumb[64*48];
403 ret = gp_file_new(&file);
408 sprintf(fn,"image%02i.pgm",i);
409 gp_file_set_type (file, GP_FILE_TYPE_PREVIEW);
410 gp_file_set_name(file, fn);
411 gp_file_set_mime_type(file, GP_MIME_PGM);
412 gp_file_append(file, THUMBHEADER, strlen(THUMBHEADER));
413 src = indexbuf+(i*64*48);
417 thumb[47*64-off+(63-x)] = src[off+x];
419 ret = gp_file_append(file,(char*)thumb,sizeof(thumb));
424 ret = gp_filesystem_append(fs, "/", fn, context);
426 /* should perhaps remove the entry again */
430 ret = gp_filesystem_set_file_noop(fs, "/", file, context);
431 if (ret != GP_OK) return ret;
433 /* we also get the fs info for free, so just set it */
434 info.file.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_NAME |
435 GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT |
437 strcpy(info.file.type,GP_MIME_PNM);
438 strcpy(info.file.name,fn);
439 info.file.width = 640;
440 info.file.height = 480;
441 info.file.size = 640*480*3+strlen(IMGHEADER);
442 info.preview.fields = GP_FILE_INFO_TYPE |
443 GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT |
445 strcpy(info.preview.type,GP_MIME_PGM);
446 info.preview.width = 64;
447 info.preview.height = 48;
448 info.preview.size = 64*48+strlen(THUMBHEADER);
449 ret = gp_filesystem_set_info_noop(fs, "/", info, context);
456 serial_image_reader(Camera *camera,CameraFile *file,int nr,unsigned char ***imagebufs,int *sizes, GPContext *context) {
457 int picnum,curread,ret=0;
458 GPPort *port = camera->port;
461 jd11_select_image(port,nr);
462 *imagebufs = (unsigned char**)malloc(3*sizeof(char**));
463 for (picnum=0;picnum<3;picnum++) {
465 sizes[picnum] = jd11_imgsize(port);
466 (*imagebufs)[picnum]=(unsigned char*)malloc(sizes[picnum]+400);
467 _send_cmd(port,0xfff1);
468 id = gp_context_progress_start (context, sizes[picnum],
469 _("Downloading data..."));
470 while (curread<sizes[picnum]) {
471 int readsize = sizes[picnum]-curread;
472 if (readsize > 200) readsize = 200;
473 ret=getpacket(port,(*imagebufs)[picnum]+curread,readsize);
479 gp_context_progress_update (context, id, curread);
480 if (gp_context_cancel (context) == GP_CONTEXT_FEEDBACK_CANCEL) {
482 /* What to do ... Just free the stuff we allocated for now. */
483 for (j=0;j<picnum;j++)
484 free((*imagebufs)[picnum]);
486 return GP_ERROR_CANCEL;
488 _send_cmd(port,0xfff1);
490 gp_context_progress_stop (context, id);
498 Camera *camera, CameraFile*file, int nr, int raw, GPContext *context
500 unsigned char *s,*uncomp[3],**imagebufs;
505 ret = serial_image_reader(camera,file,nr,&imagebufs,sizes, context);
508 uncomp[0] = malloc(320*480);
509 uncomp[1] = malloc(320*480/2);
510 uncomp[2] = malloc(320*480/2);
511 if (sizes[0]!=115200) {
512 picture_decomp_v1(imagebufs[0],uncomp[0],320,480);
513 picture_decomp_v1(imagebufs[1],uncomp[1],320,480/2);
514 picture_decomp_v1(imagebufs[2],uncomp[2],320,480/2);
516 picture_decomp_v2(imagebufs[0],uncomp[0],320,480);
517 picture_decomp_v2(imagebufs[1],uncomp[1],320,480/2);
518 picture_decomp_v2(imagebufs[2],uncomp[2],320,480/2);
520 gp_file_append(file, IMGHEADER, strlen(IMGHEADER));
521 data = malloc(640*480*3);
523 unsigned char *bayerpre;
524 s = bayerpre = malloc(640*480);
525 /* note that picture is upside down and left<->right mirrored */
530 /* G B G B G B G B G */
531 *s++ = uncomp[2][(h/2)*320+w];
532 *s++ = uncomp[0][h*320+w];
534 /* R G R G R G R G R */
535 *s++ = uncomp[0][h*320+w];
536 *s++ = uncomp[1][(h/2)*320+w];
540 gp_bayer_decode(bayerpre,640,480,data,BAYER_TILE_RGGB);
544 for (h=480;h--;) { /* upside down */
546 for (w=640;w--;) { /* right to left */
547 /* and images are in green red blue */
548 *s++=uncomp[1][(h/2)*320+(w/2)];
549 *s++=uncomp[0][h*320+(w/2)];
550 *s++=uncomp[2][(h/2)*320+(w/2)];
554 free(uncomp[0]);free(uncomp[1]);free(uncomp[2]);
555 free(imagebufs[0]);free(imagebufs[1]);free(imagebufs[2]);free(imagebufs);
556 gp_file_append(file, (char*)data, 640*480*3);