/* Open Digita Services -- Camera Device Protocol definitions. Copyright (C) 1998, 1999 James C. Thompson Copyright (C) 1998, 1999 Viljo Hakala This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*-------------------------------------------------------------------------- System include files */ #if defined(HAVE_CONFIG_H) #include "config.h" #endif #if defined(HAVE_UNISTD_H) #include #endif #include #include #include /*-------------------------------------------------------------------------- Local include files */ #include "cameraP.h" #include "camera.h" #include "cdpP.h" #include "misc.h" #include "receive.h" #include "send.h" #include "nss.h" #include "usb.h" /* Start Editing Here: (please keep this between headers and code. */ /* These are declared in system header files, but for some reason, the strict ANSI checking in gcc doesn't seem to acknowledge those declarations. */ #if defined(__SVR4) || defined(__BEOS__) #include /* hack to add cfmakeraw(), in future check with autoconf */ void cfmakeraw(struct termios *tty) { tty->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); tty->c_oflag &= ~OPOST; tty->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); tty->c_cflag &= ~(CSIZE|PARENB); tty->c_cflag |= CS8; } #else extern void cfmakeraw(struct termios *); #endif ODSCamera odsCreateCamera() { /* Allocate a camera */ ODSCamera camera = (ODSCamera) malloc(sizeof(ODSCameraRec)); if (camera == 0) { return camera; } /* Initialize its fields to default values. */ camera->type = ods_unknown; camera->mode = ods_closed; camera->fd = -1; camera->buffer = 0; camera->data_speed = 9600; camera->timeout = 3000; /* Default to half-sec timeout. */ camera->exit_on_error = 1; camera->error = kODSNoErr; camera->send_message = 0; camera->receive_message = 0; return camera; } ODSResult odsDestroyCamera(ODSCamera camera) { /* Release the memory we've used. */ free(camera); return kODSNoErr; } ODSResult odsOpenNSS(ODSCamera camera, const char *device, unsigned long req_speed) { if ((camera == 0) || (device == 0)) { #if defined(DEBUG) printf("Null camera or device.\n"); #endif return kODSParamError; } if ((camera->mode != ods_closed) || (camera->fd >= 0)) { #if defined(DEBUG) printf("Camera already open.\n"); #endif return camera->error = kODSAlreadyOpen; /* Assignment */ } camera->send_message = nss_send_message; camera->receive_message = nss_receive_message; if (nss_open(camera, device, req_speed) != 0) { return camera->error; } return kODSNoErr; } ODSResult odsCloseNSS(ODSCamera camera) { /* Set the camera mode. */ camera->mode = ods_closed; nss_close(camera); return kODSNoErr; } ODSResult odsOpenUSB(ODSCamera camera, const char *device) { char buffer[USB_QUANTA]; if ((camera == 0) || (device == 0)) { #if defined(DEBUG) printf("Null camera or device.\n"); #endif return kODSParamError; } if ((camera->mode != ods_closed) || (camera->fd >= 0)) { #if defined(DEBUG) printf("Camera already open.\n"); #endif return camera->error = kODSAlreadyOpen; /* Assignment */ } camera->send_message = usb_send_message; camera->receive_message = usb_receive_message; if (usb_open(camera, device) != 0) { return camera->error; } /* Read the USB quanta from the camera; this should flush any bytes remaining in the driver from previous (interrupted) ks runs. */ read(camera->fd, buffer, USB_QUANTA); return kODSNoErr; } ODSResult odsCloseUSB(ODSCamera camera) { /* Set the camera mode. */ camera->mode = ods_closed; usb_close(camera); return kODSNoErr; } /*-------------------------------------------------------------------------- Product and Image Information Commands */ ODSResult odsGetProductInfo(ODSCamera camera, PName pname, ResLength *reslength, PNameTypeValueStruct *valuelist, unsigned int valuelen) { /* The message length depends on whether a pname was specified */ unsigned long send_length = (pname == 0) ? 0 : 4; /**** Send phase ****/ begin_send(camera, send_length, ods_get_product_info); /* Begin sending command-specific parameters. */ if (pname != 0) { send_uint(camera, pname); } end_send(camera); usleep(2000); /**** Receive phase ****/ /* Begin receiving command-specific results. */ { unsigned int i; unsigned long length; begin_rec(camera, &length); rec_uint(camera, reslength); for (i = 0; i < *reslength; i++) { PNameTypeValueStruct ptvs; rec_ptvs(camera, &ptvs); if (i < valuelen) { valuelist[i] = ptvs; } } } end_rec(camera); return kODSNoErr; } ODSResult odsSetProductInfo(ODSCamera camera, UInteger reqlength, PNameTypeValueStruct *list, UInteger *driveno, String *path, SInteger *availablespace) { unsigned long length; unsigned long send_length = sizeof(reqlength) + sizeof(list) + sizeof(driveno) + sizeof(path) + sizeof(availablespace); /**** Send phase ****/ begin_send(camera, send_length, ods_set_product_info); /* Begin sending command-specific parameters. */ send_uint(camera, reqlength); send_ptvs(camera, list); end_send(camera); usleep(2000); /**** Receive phase ****/ /* Begin receiving command-specific results. */ begin_rec(camera, &length); rec_uint(camera, driveno); rec_string(camera, path); rec_sint(camera, availablespace); end_rec(camera); return kODSNoErr; } ODSResult odsGetImageSpecifications(ODSCamera camera, ImageSpecificationList *specificationlist) { /**** Send phase ****/ unsigned long length; begin_send(camera, 0, ods_get_image_specifications); end_send(camera); usleep(2000); /**** Receive phase ****/ /* Begin receiving command-specific results. */ begin_rec(camera, &length); rec_uint(camera, &specificationlist->ccd.pattern); rec_uint(camera, &specificationlist->ccd.pixels_horizontal); rec_uint(camera, &specificationlist->ccd.pixels_vertical); rec_uint(camera, &specificationlist->ccd.ring_pixels_horizontal); rec_uint(camera, &specificationlist->ccd.ring_pixels_vertical); rec_uint(camera, &specificationlist->ccd.bad_columns); rec_uint(camera, &specificationlist->ccd.bad_pixels); rec_uint(camera, &specificationlist->thumbnail.type); rec_uint(camera, &specificationlist->thumbnail.pixels_horizontal); rec_uint(camera, &specificationlist->thumbnail.pixels_vertical); rec_uint(camera, &specificationlist->thumbnail.file_size); rec_uint(camera, &specificationlist->screennail.type); rec_uint(camera, &specificationlist->screennail.pixels_horizontal); rec_uint(camera, &specificationlist->screennail.pixels_vertical); rec_uint(camera, &specificationlist->focus_zone.type); rec_uint(camera, &specificationlist->focus_zone.number_horizontal_zones); rec_uint(camera, &specificationlist->focus_zone.number_vertical_zones); rec_uint(camera, &specificationlist->focus_zone.origin_horizontal_zones); rec_uint(camera, &specificationlist->focus_zone.origin_vertical_zones); rec_uint(camera, &specificationlist->focus_zone.horizontal_zone_size); rec_uint(camera, &specificationlist->focus_zone.vertical_zone_size); rec_uint(camera, &specificationlist->exposure_zone.type); rec_uint(camera, &specificationlist->exposure_zone.number_horizontal_zones); rec_uint(camera, &specificationlist->exposure_zone.number_vertical_zones); rec_uint(camera, &specificationlist->exposure_zone.origin_horizontal_zones); rec_uint(camera, &specificationlist->exposure_zone.origin_vertical_zones); rec_uint(camera, &specificationlist->exposure_zone.horizontal_zone_size); rec_uint(camera, &specificationlist->exposure_zone.vertical_zone_size); end_rec(camera); return kODSNoErr; } /*-------------------------------------------------------------------------- Status Commands */ ODSResult odsGetCameraStatus(ODSCamera camera, BitFlags *systemstatus, BitFlags *capturestatus, BitFlags *vendorstatus) { /* The message length depends on whether a pname was specified */ /**** Send phase ****/ begin_send(camera, 0, ods_get_camera_status); end_send(camera); usleep(2000); /**** Receive phase ****/ /* Begin receiving command-specific results. */ { unsigned long length; begin_rec(camera, &length); rec_bitflags(camera, systemstatus); rec_bitflags(camera, capturestatus); rec_bitflags(camera, vendorstatus); end_rec(camera); } return kODSNoErr; } ODSResult odsGetError(ODSCamera camera, ErrorData *errordata) { unsigned long length; begin_send(camera, 0, ods_get_error); end_send(camera); usleep(2000); begin_rec(camera, &length); rec_uint(camera, &errordata->Date); rec_uint(camera, &errordata->Time); rec_sint(camera, &errordata->ErrorCode); rec_string(camera, &errordata->ErrorDescription); end_rec(camera); return kODSNoErr; } /*-------------------------------------------------------------------------- Camera Capabilities and State Commands */ ODSResult odsGetCameraCapabilities(ODSCamera camera, PName pname, UInteger *reslength, CapabilitiesData *capabilitiesdata, unsigned long valuelen) { /* The message length depends on whether a pname was specified */ unsigned long send_length = (pname == 0) ? 0 : 4; /**** Send phase ****/ begin_send(camera, send_length, ods_get_camera_capabilities); /* Begin sending command-specific parameters. */ if (pname != 0) { send_uint(camera, pname); } end_send(camera); usleep(2000); /**** Receive phase ****/ /* Begin receiving command-specific results. */ { unsigned int i; unsigned long length; begin_rec(camera, &length); rec_uint(camera, reslength); for (i = 0; i < *reslength; i++) { CapabilitiesData cdata; rec_pname(camera, &cdata.Name); if (i < valuelen) { capabilitiesdata[i] = cdata; } } } end_rec(camera); return kODSNoErr; } ODSResult odsGetCameraState(ODSCamera camera, PName pname, UInteger *reslength, PNameTypeValueStruct *typevaluelist, unsigned long valuelen) { unsigned long send_length = (pname == 0) ? 0 : sizeof(pname); begin_send(camera, send_length, ods_get_camera_state); if (send_length) { send_uint(camera, pname); } end_send(camera); usleep(2000); /* Begin receiving command-specific results. */ { unsigned int i; unsigned long length; begin_rec(camera, &length); rec_uint(camera, reslength); for (i = 0; i < *reslength; i++) { PNameTypeValueStruct ptvs; rec_ptvs(camera, &ptvs); if (i < valuelen) { typevaluelist[i] = ptvs; } } } end_rec(camera); return kODSNoErr; } ODSResult odsSetCameraState(ODSCamera camera, const PNameValueStruct *valuestruct) { unsigned long length; unsigned long send_length = (valuestruct->Name) ? sizeof(valuestruct->Name) + sizeof(valuestruct->Data.UInt) : 0; begin_send(camera, send_length, ods_set_camera_state); if (send_length) { send_uint(camera, valuestruct->Name); } if (valuestruct->Name) { send_uint(camera, valuestruct->Data.UInt); } end_send(camera); usleep(2000); begin_rec(camera, &length); end_rec(camera); return kODSNoErr; } ODSResult odsGetCameraDefault(ODSCamera camera, UInteger defaultsource, PName pname, UInteger *reslength, PNameTypeValueStruct *typevaluelist, unsigned long valuelen) { unsigned long send_length = (pname == 0) ? 0 : sizeof(pname); send_length += sizeof(defaultsource); begin_send(camera, send_length, ods_get_camera_defaults); send_uint(camera, defaultsource); if (pname) { send_uint(camera, pname); } end_send(camera); usleep(2000); /* Begin receiving command-specific results. */ { unsigned int i; unsigned long length; begin_rec(camera, &length); rec_uint(camera, reslength); for (i = 0; i < *reslength; i++) { PNameTypeValueStruct list; rec_ptvs(camera, &list); if (i < valuelen) { typevaluelist[i] = list; } } } end_rec(camera); return kODSNoErr; } ODSResult odsSetCameraDefault(ODSCamera camera, UInteger updatesource, PNameValueStruct *valuestruct) { unsigned long length; unsigned long send_length = sizeof(updatesource) + sizeof(PNameValueStruct); begin_send(camera, send_length, ods_set_camera_defaults); send_uint(camera, updatesource); if (valuestruct->Name) { send_uint(camera, valuestruct->Name); } send_uint(camera, valuestruct->Data.UInt); end_send(camera); begin_rec(camera, &length); end_rec(camera); return kODSNoErr; } ODSResult odsRestoreCameraState(ODSCamera camera, UInteger defaultsource, PName pname) { unsigned long length; unsigned long send_length = (pname == 0) ? 0 : sizeof(pname); send_length += sizeof(defaultsource); begin_send(camera, send_length, ods_restore_camera_states); send_uint(camera, defaultsource); if (pname) { send_uint(camera, pname); } begin_rec(camera, &length); end_rec(camera); return kODSNoErr; } /*-------------------------------------------------------------------------- Scene Analysis Command */ ODSResult odsGetSceneAnalysis(ODSCamera camera, UInteger analysistype, Boolean preview, UInteger *reslength, UInteger *sceneanalysisdata) { unsigned long send_length = sizeof(analysistype) + sizeof(preview); begin_send(camera, send_length, ods_get_scene_analysis); send_uint(camera, analysistype); send_boolean(camera, preview); end_send(camera); usleep(2000); /* Begin receiving command-specific results. */ { unsigned int i; unsigned long length; begin_rec(camera, &length); rec_uint(camera, reslength); for (i = 0; i < *reslength; i++) { rec_uint(camera, &sceneanalysisdata[i]); } } end_rec(camera); return kODSNoErr; } /*-------------------------------------------------------------------------- Power and Capture Commands */ ODSResult odsGetPowerMode(ODSCamera camera, UInteger *PowerState) { unsigned long length; /**** Send phase ****/ begin_send(camera, 0, ods_get_power_mode); end_send(camera); usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); rec_uint(camera, PowerState); end_rec(camera); return kODSNoErr; } ODSResult odsSetPowerMode(ODSCamera camera) { unsigned long length; /**** Send phase ****/ begin_send(camera, 0, ods_set_power_mode); end_send(camera); usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); end_rec(camera); return kODSNoErr; } ODSResult odsGetS1Mode(ODSCamera camera, Boolean *s1mode) { unsigned long length; /**** Send phase ****/ begin_send(camera, 0, ods_get_s1_mode); end_send(camera); usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); rec_boolean(camera, s1mode); end_rec(camera); return kODSNoErr; } ODSResult odsSetS1Mode(ODSCamera camera, Boolean s1mode) { unsigned long length; /**** Send phase ****/ begin_send(camera, sizeof(s1mode), ods_set_s1_mode); send_boolean(camera, s1mode); end_send(camera); usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); end_rec(camera); return kODSNoErr; } ODSResult odsStartCapture(ODSCamera camera) { unsigned long extra = 0; unsigned long length; unsigned long timeout_save; #if defined(DEBUG) printf("ostStartCapture\n"); #endif /**** Send phase ****/ begin_send(camera, sizeof(extra), ods_start_capture); send_uint(camera, extra); end_send(camera); usleep(2000); /**** Receive phase ****/ /* Save the existing timeout and increase it by 3 sec before going into the capture. */ timeout_save = camera->timeout; camera->timeout += 3000; begin_rec(camera, &length); end_rec(camera); /* Restore the existing timeout. */ camera->timeout = timeout_save; return kODSNoErr; } /*-------------------------------------------------------------------------- File Commands */ ODSResult odsGetFileList(ODSCamera camera, UInteger listorder, const FileNameStruct *filename, UInteger *reslength, ResFileItem *resfilelist, int valuelen) { unsigned long length; unsigned int i; /* * The message length depends on whether a filename was specified */ unsigned long send_length = (filename == 0) ? 4 : 56; /**** Send phase ****/ /* Begin with command */ begin_send(camera, send_length, ods_get_file_list); /* Send list order */ send_uint(camera, listorder); if (filename != 0) { /* Send the filename if there is one. */ send_filename(camera, filename); } end_send(camera); /* done sending */ usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); /* Begin receiving */ rec_uint(camera, reslength); /* Get result length */ /* Loop over file items in result-list. */ for (i = 0; i < *reslength; i++) { ResFileItem file; /* Receive the file item */ rec_fileitem(camera, &file); /* If there's room in the return list, save the file item. */ if (i < (unsigned) valuelen) { resfilelist[i] = file; } } end_rec(camera); /* Done receiving */ return kODSNoErr; } ODSResult odsGetNewFileList(ODSCamera camera, UInteger *reslength, ResFileItem *resfilelist, unsigned int valuelen) { unsigned long length; unsigned int i; /* The message length depends on whether a filename was specified */ unsigned long send_length = 0; /**** Send phase ****/ begin_send(camera, send_length, ods_get_new_file_list); end_send(camera); /* done sending */ usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); /* Begin receiving */ rec_uint(camera, reslength); /* Get result length */ /* Loop over file items in result-list. */ for (i = 0; i < *reslength; i++) { ResFileItem file; /* Receive the file item */ rec_fileitem(camera, &file); /* If there's room in the return list, save the file item. */ if (i < valuelen) { resfilelist[i] = file; } } end_rec(camera); /* Done receiving */ return kODSNoErr; } ODSResult odsGetFileData(ODSCamera camera, const FileNameStruct *filename, UInteger dataselector, PartialTag *partialtag, void *filedata, UInteger *thumb_len, UInteger *thumb_w, UInteger *thumb_h, UInteger *unknown) { UInteger unused; ODSResult rc; unsigned long length; /* Length of message */ unsigned long dllength; /* Number of bytes downloaded */ dllength = partialtag->Length; #if defined(DEBUG) printf("odsGetFileData -- \n"); #endif #if defined(DEBUG) printf("odsGetFileData: partial length is %ld bytes.\n", dllength); #endif /**** Send phase ****/ /* Protocol: Command -> FilenameStruct -> DataSelector -> PartialTag -> */ camera->exit_on_error = 0; begin_send(camera, 68, ods_get_file_data); send_filename(camera, filename); send_uint(camera, dataselector); send_partialtag(camera, partialtag); end_send(camera); usleep(2000); /**** Receive phase ****/ rc = begin_rec(camera, &length); if (rc != kODSNoErr) { end_rec(camera); return rc; } rec_partialtag(camera, partialtag); /* If we were expecting to download more data than was available, then reduce the download length to the number available. */ if (dllength > partialtag->Length) { dllength = partialtag->Length; } if (dataselector != 0) { if (thumb_len == 0) { thumb_len = &unused; } if (thumb_w == 0) { thumb_w = &unused; } if (thumb_h == 0) { thumb_h = &unused; } if (unknown == 0) { unknown = &unused; } /* We're downloading a thumbnail. There are 16 extra bytes to download. */ rec_uint(camera, thumb_len); rec_uint(camera, thumb_w); rec_uint(camera, thumb_h); rec_uint(camera, unknown); } #if defined(DEBUG) printf("odsGetFileData: asking rec_bytes for %ld bytes.\n", dllength); #endif rc = rec_bytes(camera, filedata, dllength, 1); if (rc != kODSNoErr) { return rc; } rc = end_rec(camera); if (rc != kODSNoErr) { printf("-"); fflush(stdout); rc = kODSNoErr; /* We can actually ignore this. */ } camera->exit_on_error = 1; return rc; } ODSResult odsSetFileData(ODSCamera camera, const FileNameStruct *filename, UInteger dataselector, const PartialTag *partialtag, const void *filedata) { (void) camera; (void) filename; (void) dataselector; (void) partialtag; (void) filedata; return kODSUnimplemented; } ODSResult odsEraseFile(ODSCamera camera, const FileNameStruct *filename) { unsigned long length; /* The message length depends on whether a filename was specified */ unsigned long send_length = (filename == 0) ? 0 : sizeof(FileNameStruct); /**** Send phase ****/ begin_send(camera, send_length, ods_erase_file); /* Begin with command */ if (filename != 0) { /* Send the filename if there is one. */ send_filename(camera, filename); } send_uint(camera, 0); end_send(camera); /* done sending */ usleep(2000); begin_rec(camera, &length); end_rec(camera); return kODSNoErr; } ODSResult odsGetStorageStatus(ODSCamera camera, UInteger *takencount, UInteger *availablecount, SInteger *rawcount) { unsigned long length; /* The message length depends on whether a filename was specified */ /**** Send phase ****/ /* Begin with command */ begin_send(camera, 0, ods_get_storage_status); end_send(camera); /* done sending */ usleep(2000); begin_rec(camera, &length); rec_uint(camera, takencount); rec_uint(camera, availablecount); rec_sint(camera, rawcount); end_rec(camera); return kODSNoErr; } ODSResult odsGetFileTag(ODSCamera camera, const FileNameStruct *name, PName pname, ResLength *reslength, PNameTypeValueStruct *valuelist, int valuelen) { /* The message length depends on whether a pname was specified */ unsigned long send_length = 56; /* (pname == 0) ? 52 : 56; */ #if defined(DEBUG) printf("odsGetFileTag -- \n"); #endif /**** Send phase ****/ begin_send(camera, send_length, ods_get_file_tag); send_filename(camera, name); /* FilenameStruct */ send_uint(camera, pname); end_send(camera); usleep(2000); /**** Receive phase ****/ /* Begin receiving command-specific results. */ { unsigned int i; unsigned long length; begin_rec(camera, &length); if (camera->result != 0) { fprintf(stderr, "Error in odsGetFileTag\n"); } /* Receive the number of PNameTypeValueStructs in the reply. */ rec_uint(camera, reslength); /* Loop over each of the structs, reading each. */ for (i = 0; i < *reslength; i++) { PNameTypeValueStruct ptvs; /* Read the reply struct */ rec_ptvs(camera, &ptvs); /* If there's room in the caller's reply list, store the struct */ if (i < (unsigned int) valuelen) { valuelist[i] = ptvs; } } } end_rec(camera); return kODSNoErr; } ODSResult odsSetUserFileTag(ODSCamera camera, const FileNameStruct *filename, const PNameValueStruct *valuestruct) { (void) camera; (void) filename; (void) valuestruct; return kODSUnimplemented; } /*-------------------------------------------------------------------------- Clock Commands */ ODSResult odsSetClock(ODSCamera camera, const ClockDateTime *datetime) { unsigned long length; /**** Send phase ****/ begin_send(camera, sizeof(ClockDateTime), ods_set_clock); send_uint(camera, datetime->ClockDate); send_uint(camera, datetime->ClockTime); end_send(camera); usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); end_rec(camera); return kODSNoErr; } ODSResult odsGetClock(ODSCamera camera, ClockDateTime *datetime) { unsigned long length; /**** Send phase ****/ begin_send(camera, 0, ods_get_clock); end_send(camera); usleep(2000); /**** Receive phase ****/ begin_rec(camera, &length); rec_uint(camera, &datetime->ClockDate); rec_uint(camera, &datetime->ClockTime); end_rec(camera); return kODSNoErr; } ODSResult odsGetInterfaceTimeout(ODSCamera camera, Timeout *timeout) { (void) camera; (void) timeout; return kODSUnimplemented; } ODSResult odsSetInterfaceTimeout(ODSCamera camera, const Timeout *timeout) { (void) camera; (void) timeout; return kODSUnimplemented; } void odsResetCamera(ODSCamera camera) { camera->mode = ods_presend; }