#include "camera.h" #include "lolevel.h" #include "platform.h" #include "raw_buffer.h" #include "conf.h" #include "math.h" #include "levent.h" #include "ptp_chdk.h" #include "live_view.h" #include "usb_remote.h" #include "exmem.h" #include "stdio.h" // arbitrary timeout for canon heap semaphore #if !CAM_DRYOS #define CANON_HEAP_SEM_TIMEOUT 1000 extern int canon_heap_sem; #endif //---------------------------------------------------------------------------- // Char Wrappers (VxWorks - ARM stubs) #if !CAM_DRYOS int isdigit(int c) { return _isdigit(c); } int isspace(int c) { return _isspace(c); } int isalpha(int c) { return _isalpha(c); } int isupper(int c) { return _isupper(c); } int islower(int c) { return _islower(c); } int ispunct(int c) { return _ispunct(c); } int isxdigit(int c) { return _isxdigit(c); } int tolower(int c) { return _tolower(c); } int toupper(int c) { return _toupper(c); } #endif //---------------------------------------------------------------------------- int submenu_sort_arm(const void* v1, const void* v2) { extern int submenu_sort(const void* v1, const void* v2); return submenu_sort(v1, v2); } //---------------------------------------------------------------------------- void msleep(long msec) { _SleepTask(msec); } #ifndef CAM_DRYOS long task_lock() { return _taskLock(); } long task_unlock() { return _taskUnlock(); } const char *task_name(int id) { return _taskName(id); } int task_id_list_get(int *idlist,int size) { return _taskIdListGet(idlist,size); } #endif long get_property_case(long id, void *buf, long bufsize) { // workaround for missing PROPCASE_SHOOTING #if CAM_PROPSET == 7 || CAM_PROPSET == 9 || CAM_PROPSET == 10 || CAM_PROPSET == 11 || CAM_PROPSET == 12 || CAM_PROPSET == 13 if(id==PROPCASE_SHOOTING) { int r=_GetPropertyCase(PROPCASE_SHOOTING_STATE, buf, bufsize); // 1 50ms after half press, 2 after exp hook, 3 while shooting // propset 6 has similar procase id 351, goes 3->0 when get_shooting goes false // propset 4 and 5 id 352 is similar but only goes to 2 // (4 per https://chdk.setepontos.com/index.php?topic=11604.msg113712#msg113712) if(*(char *)buf > 1) { *(char *)buf = 1; } else { *(char *)buf = 0; } return r; } #endif return _GetPropertyCase(id, buf, bufsize); } long set_property_case(long id, void *buf, long bufsize) { // ignore set on fake prop #if CAM_PROPSET == 7 || CAM_PROPSET == 9 || CAM_PROPSET == 10 || CAM_PROPSET == 11 || CAM_PROPSET == 12 || CAM_PROPSET == 13 if(id==PROPCASE_SHOOTING) { return 0; } #endif return _SetPropertyCase(id, buf, bufsize); } // FlashParamsTable entries point to this structure #if CAM_FLASHPARAMS_VERSION == 2 // ixus30_sd200, ixus40_sd300 typedef struct { short unk1; short unk2; void* data; // Pointer to param data short size; // param size short unk3; int unk4; short unk5; short unk6; } flashParam; #else // version 3 (every camera from 2005 on) typedef struct { void* data; // Pointer to param data short unk1; short size; // param size short unk2; short unk3; short unk4; char unk5; char unk6; } flashParam; #endif // CAM_FLASHPARAMS_VERSION short get_parameter_size(long id) { extern flashParam* FlashParamsTable[]; if ((id >= 0) && (id < get_flash_params_count())) return FlashParamsTable[id]->size; return 0; } long get_parameter_data(long id, void *buf, long bufsize) { return _GetParameterData(id|PARAMETER_DATA_FLAG, buf, bufsize); } long set_parameter_data(long id, void *buf, long bufsize) { return _SetParameterData(id|PARAMETER_DATA_FLAG, buf, bufsize); } short __attribute__((weak)) get_uiprop_value(unsigned long id) { // avoid asserts: return 0 if id is above limit if (id >= (unsigned long)uiprop_count) return 0; return _PTM_GetCurrentItem(id|0x8000); } void mark_filesystem_bootable() { #ifdef CAM_DRYOS_2_3_R47 // DryOS release 47 (2011) no longer has the UpdateMBROnFlash function to write the master boot record on // the SD card. Instead it has seperate functions for writing the 'BOOTDISK' and 'SCRIPT' signatures to // the MBR. The firmware function also takes care of writing the bootdisk signature to the correct location // for FAT32 formatted cards. _MakeSDCardBootable(0); #else _UpdateMBROnFlash(0, 0x40, "BOOTDISK"); #endif } // d6 cams must define, don't have usable _RefreshPhysicalScreen #ifndef THUMB_FW void __attribute__((weak)) vid_bitmap_refresh() { _RefreshPhysicalScreen(1); } #endif long lens_get_zoom_pos() { return _GetZoomLensCurrentPosition(); } long lens_get_zoom_point() { return _GetZoomLensCurrentPoint(); } #ifdef CAM_ILC void lens_set_zoom_point(__attribute__ ((unused))long newpt) {} void lens_set_zoom_speed(__attribute__ ((unused))long newspd) {} #else // !CAM_ILC #if defined(CAM_USE_ALT_SET_ZOOM_POINT) static int mz_speed = 3; // max speed on cameras with multi-speed zoom, ignored on others #endif void lens_set_zoom_point(long newpt) { if (newpt < 0) { newpt = 0; } else if (newpt >= zoom_points) { newpt = zoom_points-1; } #if defined(CAM_USE_ALT_SET_ZOOM_POINT) if (lens_get_zoom_point() != newpt) { int digizoom_pos; get_property_case(PROPCASE_DIGITAL_ZOOM_POSITION,&digizoom_pos,sizeof(digizoom_pos)); // check current digital zoom mode & state // state == 1 && mode == 0 --> Digital Zoom Standard if ((shooting_get_digital_zoom_state() == 1) && (shooting_get_digital_zoom_mode() == 0) && (digizoom_pos != 0)) { // reset digital zoom in case camera is in this zoom range extern void _PT_MoveDigitalZoomToWide(); _PT_MoveDigitalZoomToWide(); } // starting around digic 4 - _MoveZoomLensWithPoint crashes many cameras // _PT_MoveOpticalZoomAt works, and updates PROPCASE_OPTICAL_ZOOM_POSITION; but doesn't wait for zoom to finish // _MoveOpticalZoom at is underlying function that accepts speed // updates jpeg engine distortion correction setting, maintains focus position extern void _MoveOpticalZoomAt(long pt,int speed); _MoveOpticalZoomAt(newpt,mz_speed); // have to sleep here, zoom_busy set in another task, without sleep this will hang while (zoom_busy) msleep(10); // g10,g12 & sx30 only use this value for optical zoom zoom_status=ZOOM_OPTICAL_MAX; } #else // !(CAM_USE_ALT_SET_ZOOM_POINT) _MoveZoomLensWithPoint((short*)&newpt); // tight loop here hangs some cameras (the task that clears zoom_busy // is starved; seen at least on S95 and IXUS 220), so stick in a sleep while (zoom_busy) msleep(10); if (newpt==0) zoom_status=ZOOM_OPTICAL_MIN; else if (newpt >= zoom_points) zoom_status=ZOOM_OPTICAL_MAX; else zoom_status=ZOOM_OPTICAL_MEDIUM; _SetPropertyCase(PROPCASE_OPTICAL_ZOOM_POSITION, &newpt, sizeof(newpt)); #endif // !(CAM_USE_ALT_SET_ZOOM_POINT) } void lens_set_zoom_speed(long newspd) { // translate % to speed values for _MoveOpticalZoomAt // which correspond to different speeds varies by camera #if defined(CAM_USE_ALT_SET_ZOOM_POINT) if (newspd < 25) { mz_speed = 0; } else if (newspd < 50) { mz_speed = 1; } else if (newspd < 75) { mz_speed = 2; } else { mz_speed = 3; } #else // !CAM_USE_ALT_SET_ZOOM_POINT // a few old cameras support setting by % if (newspd < 5) { newspd = 5; } else if (newspd > 100) { newspd = 100; } _SetZoomActuatorSpeedPercent((short*)&newspd); #endif // !CAM_USE_ALT_SET_ZOOM_POINT } #endif // !CAM_ILC void lens_set_focus_pos(long newpos) { if (newpos >= CAMERA_MAX_DIST) newpos = INFINITY_DIST; // Set to infinity value that will work on all cameras _MoveFocusLensToDistance((short*)&newpos); while ((shooting_is_flash_ready()!=1) || (focus_busy)) msleep(10); newpos = _GetFocusLensSubjectDistance(); _SetPropertyCase(PROPCASE_SUBJECT_DIST1, &newpos, sizeof(newpos)); _SetPropertyCase(PROPCASE_SUBJECT_DIST2, &newpos, sizeof(newpos)); } void play_sound(unsigned sound) { static const int sounds[]={ 0x2001, //startup sound 0x2002, //shutter sound 0x2003, //button press sound 0x2004, //self-timer sound 0xC211, //short beep 50000, // AF confirmation 0xC507, // error beep imo 0x400D, // LONG ERROR BEEP CONTINIUOUS- warning, cannot be stopped (yet) }; if(sound >= sizeof(sounds)/sizeof(sounds[0])) return; _PT_PlaySound(sounds[sound], 0, 0); } long stat_get_vbatt() { return _VbattGet(); } //======================================================================== // NOTE : some early DryOS cameras need a pointer rather than a value and the // xus30 & 40 want a char * string here. Override this funcion in camera's // lib.c file if impelementing remote via battery 3rd terminal functionality. // see http://chdk.setepontos.com/index.php?topic=10385.msg109353#msg109353 // int __attribute__((weak)) GetAdChValue(int channel) { #ifdef CAM_DRYOS return _GetAdChValue(channel); #else return _GetAdChValue(&channel); #endif } int get_battery_temp() { return _GetBatteryTemperature(); } int get_ccd_temp() { return _GetCCDTemperature(); } int get_optical_temp() { return _GetOpticalTemperature(); } long get_tick_count() { long t; #if !CAM_DRYOS _GetSystemTime(&t); return t; #else return (int)_GetSystemTime(&t); #endif } #if CAM_HAS_ND_FILTER void PutInNdFilter() { _PutInNdFilter(); } void PutOutNdFilter() { _PutOutNdFilter(); } #endif short shooting_get_nd_value_ev96(void) { #if CAM_HAS_ND_FILTER return _get_nd_value(); #else return 0; #endif } short shooting_get_nd_current_ev96(void) { #if CAM_HAS_ND_FILTER return _get_current_nd_value(); #else return 0; #endif } long shooting_get_current_tv96() { // old cameras crash if _GetCurrentShutterSpeed called when inactive if(!shooting_get_imager_active()) { return SHOOTING_TV96_INVALID; } return _GetCurrentShutterSpeed(); } long shooting_get_current_av96() { return _GetCurrentAvValue(); } long shooting_get_current_delta_sv96() { return _get_current_deltasv(); } long shooting_get_current_base_sv96() { return _GetCurrentDriveBaseSvValue(); } long IsStrobeChargeCompleted() { return _IsStrobeChargeCompleted(); } void SetCurrentCaptureModeType() { _SetCurrentCaptureModeType(); } #if CAM_HAS_IRIS_DIAPHRAGM // returns available Av range in AV96 on cameras with iris. // Function exists on a few later cameras without iris, behavior unknown. // Appears to be the full range, including smaller (higher F/ number) than available in Canon UI. // Note Min = smallest physical aperture = largest Av96 value short GetUsableMinAv(void) { return _GetUsableMinAv(); } short GetUsableMaxAv(void) { return _GetUsableMaxAv(); } #endif #if CAM_CAN_UNLOCK_OPTICAL_ZOOM_IN_VIDEO void UnsetZoomForMovie() { _UnsetZoomForMovie(); } #endif #ifdef CAM_AV_OVERRIDE_IRIS_FIX int MoveIrisWithAv(short *v) { return _MoveIrisWithAv(v); } #endif #if CAM_EV_IN_VIDEO void ExpCtrlTool_StartContiAE(int v1, int v2) { _ExpCtrlTool_StartContiAE(v1,v2); } void ExpCtrlTool_StopContiAE(int v1, int v2) { _ExpCtrlTool_StopContiAE(v1, v2); } short SetAE_ShutterSpeed(short *tv) { return _SetAE_ShutterSpeed(tv); } #endif //---------------------------------------------------------------------------- // I/O wrappers extern int fileio_semaphore; int takeFileIOSemaphore() { int timeout = CAM_FILEIO_SEM_TIMEOUT; #if defined(CAM_IS_VID_REC_WORKS) if (is_video_recording()) timeout = CAM_FILEIO_SEM_TIMEOUT_VID; #endif #if defined(OPT_FILEIO_STATS) int t = get_tick_count(); #endif // Check fileio semaphore with timeout, if not available we are probably recording video if (_TakeSemaphore(fileio_semaphore,timeout) & 1) { #if defined(OPT_FILEIO_STATS) camera_info.fileio_stats.fileio_semaphore_errors++; #endif return 0; } #if defined(OPT_FILEIO_STATS) t = get_tick_count() - t; if (t > camera_info.fileio_stats.max_semaphore_timeout) camera_info.fileio_stats.max_semaphore_timeout = t; #endif return 1; } int open (const char *name, int flags, int mode ) { #if defined(OPT_FILEIO_STATS) camera_info.fileio_stats.open_count++; #endif #if !CAM_DRYOS // Adjust O_TRUNC and O_CREAT flags for VxWorks // Remove O_APPEND flag if present (not in VxWorks) flags = (flags & ~(O_TRUNC|O_CREAT|O_APPEND)) | ((flags & (O_TRUNC|O_CREAT)) << 1); #else if(!name || name[0]!='A') return -1; #endif int haveSemaphore = takeFileIOSemaphore(); if (!haveSemaphore) #if defined(CAM_IS_VID_REC_WORKS) if (!conf.allow_unsafe_io) #endif return -1; int fd = _Open(name, flags, mode); if (haveSemaphore) _GiveSemaphore(fileio_semaphore); #if defined(OPT_FILEIO_STATS) if (fd == -1) camera_info.fileio_stats.open_fail_count++; #endif return fd; } int close (int fd) { #if defined(OPT_FILEIO_STATS) camera_info.fileio_stats.close_count++; #endif if (fd == -1) { #if defined(OPT_FILEIO_STATS) camera_info.fileio_stats.close_badfile_count++; #endif return -1; } int haveSemaphore = takeFileIOSemaphore(); if (!haveSemaphore) #if defined(CAM_IS_VID_REC_WORKS) if (!conf.allow_unsafe_io) #endif return -1; int r = _Close(fd); if (haveSemaphore) _GiveSemaphore(fileio_semaphore); #if defined(OPT_FILEIO_STATS) if (r == -1) camera_info.fileio_stats.close_fail_count++; #endif return r; } int write (int fd, const void *buffer, long nbytes) { if (fd == -1) { #if defined(OPT_FILEIO_STATS) camera_info.fileio_stats.write_badfile_count++; #endif return -1; } int haveSemaphore = takeFileIOSemaphore(); if (!haveSemaphore) #if defined(CAM_IS_VID_REC_WORKS) if (!conf.allow_unsafe_io) #endif return -1; int r = _Write(fd, buffer, nbytes); if (haveSemaphore) _GiveSemaphore(fileio_semaphore); return r; } int read (int fd, void *buffer, long nbytes) { return _Read(fd, buffer, nbytes); } int lseek (int fd, long offset, int whence) { return _lseek(fd, offset, whence); /* yes, it's lower-case lseek here since Lseek calls just lseek (A610) */ } long mkdir(const char *dirname) { #ifdef MKDIR_RETURN_ONE_ON_SUCCESS // mkdir returns 1 on success, 0 on fail. So, values are inverted, to be compatible with previous versions if(_MakeDirectory_Fut(dirname,1)) return 0; else return 1; #else return _MakeDirectory_Fut(dirname,-1); // meaning of second arg is not clear, firmware seems to use -1 #endif } long mkdir_if_not_exist(const char *dirname) { // Check if directory exists and create it if it does not. if (stat(dirname,0) != 0) return mkdir(dirname); return 0; // Success } int remove(const char *name) { #ifdef CAM_DRYOS_2_3_R39 // For DryOS R39 and later need to check if 'name' is a file or directory // and call appropriate delete function. struct stat st; if (stat(name,&st) == 0) { if (st.st_attrib & DOS_ATTR_DIRECTORY) return _DeleteDirectory_Fut(name); else return _DeleteFile_Fut(name); } return -1; // return fail - file / directory does not exist #else return _DeleteFile_Fut(name); #endif } //---------------------------------------------------------------------------- // minimal directory wrappers, rest of implementation is in core/lib_thumb.c int fw_closedir(void *d) { int have_semaphore = takeFileIOSemaphore(); if (!have_semaphore) #if defined(CAM_IS_VID_REC_WORKS) if (!conf.allow_unsafe_io) #endif return -1; extern int _closedir(void *d); int ret = _closedir(d); if (have_semaphore) _GiveSemaphore(fileio_semaphore); return ret; } #if defined(CAM_DRYOS) int get_fstype(void) { #ifdef CAM_DRYOS_2_3_R39 // fw function returns 1..3 for FAT 12-16-32, 4 for exFAT // TODO: fix this if any supported camera gets more than 1 drive OR the returned values change extern int _get_fstype(int); return _get_fstype(0); #else return 0; #endif } void *fw_opendir(const char* name) { void *ret; int have_semaphore = takeFileIOSemaphore(); if (!have_semaphore) #if defined(CAM_IS_VID_REC_WORKS) if (!conf.allow_unsafe_io) #endif return NULL; extern void *_OpenFastDir(const char* name); ret = _OpenFastDir(name); if (have_semaphore) _GiveSemaphore(fileio_semaphore); return ret; } int fw_readdir(void *d, void* dd) { extern int _ReadFastDir(void *d, void* dd); return _ReadFastDir(d, dd); } #else // Vx void *fw_opendir(const char* name) { void *ret; int have_semaphore = takeFileIOSemaphore(); if (!have_semaphore) #if defined(CAM_IS_VID_REC_WORKS) if (!conf.allow_unsafe_io) #endif return NULL; extern void *_opendir(const char* name); ret = _opendir(name); if (have_semaphore) _GiveSemaphore(fileio_semaphore); return ret; } void *fw_readdir(void *d) { extern void *_readdir(void *d); return _readdir(d); } #endif // CAM_DRYOS //----------------------------------------------------------------------------------- // Internal camera firmare 'stat' structures #if !CAM_DRYOS struct __stat // VxWorks { unsigned long st_dev; /* device ID number */ unsigned long st_ino; /* file serial number */ unsigned short st_mode; /* file mode (see below) */ short st_nlink; /* number of links to file */ short st_uid; /* user ID of file's owner */ short st_gid; /* group ID of file's group */ unsigned long st_rdev; /* device ID, only if special file */ unsigned long st_size; /* size of file, in bytes */ unsigned long st_atime; /* time of last access */ unsigned long st_mtime; /* time of last modification */ unsigned long st_ctime; /* time of last change of file status */ long st_blksize; long st_blocks; unsigned char st_attrib; /* file attribute byte (dosFs only) */ int reserved1; /* reserved for future use */ int reserved2; /* reserved for future use */ int reserved3; /* reserved for future use */ int reserved4; /* reserved for future use */ int reserved5; /* reserved for future use */ int reserved6; /* reserved for future use */ }; #else #ifndef CAM_DRYOS_2_3_R39 struct __stat // DryOS pre R39 { unsigned long st_dev; //? unsigned long st_ino; //? unsigned short st_mode; //? short st_nlink; //? short st_uid; //? short st_gid; //? unsigned long st_atime; //? unsigned long st_mtime; //? unsigned long st_ctime; //? unsigned long st_size; long st_blksize; //? long st_blocks; //? unsigned char st_attrib; int reserved1; // int reserved2; // int reserved3; // int reserved4; // int reserved5; // int reserved6; // }; #else #ifndef CAM_DRYOS_2_3_R59 struct __stat // DryOS R39...R58 { unsigned long st_unknown_1; unsigned long st_attrib; unsigned long st_size; unsigned long st_ctime; unsigned long st_mtime; unsigned long st_unknown_2; }; #else struct __stat // DryOS >= R59 { unsigned long st_unknown_1; unsigned long st_attrib; unsigned long st_size; // fixme: very likely 64bit, upper 32 bit is st_unknown_2 unsigned long st_unknown_2; unsigned long st_ctime; unsigned long st_mtime; unsigned long st_unknown_3; }; #endif//CAM_DRYOS_2_3_R59 #endif//CAM_DRYOS_2_3_R39 #endif//CAM_DRYOS int stat(const char *name, struct stat *pStat) { // sanity check. canon firmware hangup if start not from 'A/' if ( !name || (name[0] | 0x20)!='a' || name[1]!='/' ) return 1; // use temp __stat stucture to match camera firmware // and copy values across to output struct __stat lStat; int rv = _stat(name, &lStat); if (pStat) { if (rv == 0) { pStat->st_attrib = lStat.st_attrib; pStat->st_size = lStat.st_size; pStat->st_ctime = lStat.st_ctime; pStat->st_mtime = lStat.st_mtime; } else { memset( pStat, 0, sizeof(struct stat)); } } return rv; } FILE *fopen(const char *filename, const char *mode) { #ifdef CAM_DRYOS if(!filename || filename[0]!='A') { return NULL; } #endif // Check fileio semaphore, if not available we are probably recording video if (!takeFileIOSemaphore()) return NULL; _GiveSemaphore(fileio_semaphore); return (FILE *)_Fopen_Fut(filename,mode); } long fclose(FILE *f) { return _Fclose_Fut((long)f); } long fread(void *buf, long elsize, long count, FILE *f) { return _Fread_Fut(buf,elsize,count,(long)f); } long fwrite(const void *buf, long elsize, long count, FILE *f) { return _Fwrite_Fut(buf,elsize,count,(long)f); } long fseek(FILE *file, long offset, long whence) { return _Fseek_Fut((long)file,offset,whence); } long feof(FILE * file) { return _Feof_Fut((long)file); } long fflush(FILE * file) { return _Fflush_Fut((long)file); } char *fgets(char *buf, int n, FILE *f) { return _Fgets_Fut(buf,n,(int)f); } int rename(const char *oldname, const char *newname) { return _RenameFile_Fut(oldname, newname); } unsigned int GetFreeCardSpaceKb(void){ // get free clusters directly for digic >= 6, updates during video recording #ifdef THUMB_FW extern unsigned long live_free_cluster_count; unsigned long free_clusters = live_free_cluster_count; #else unsigned long free_clusters = _GetDrive_FreeClusters(0); #endif return (free_clusters*(_GetDrive_ClusterSize(0)>>9))>>1; } unsigned int GetTotalCardSpaceKb(void){ return (_GetDrive_TotalClusters(0)*(_GetDrive_ClusterSize(0)>>9))>>1; } //---------------------------------------------------------------------------- int errnoOfTaskGet(int tid) { #if !CAM_DRYOS return _errnoOfTaskGet(tid); #else (void)tid; return 0; #endif } //---------------------------------------------------------------------------- // String wrappers long strlen(const char *s) { return _strlen(s); } int strcmp(const char *s1, const char *s2) { return _strcmp(s1, s2); } int strncmp(const char *s1, const char *s2, long n) { return _strncmp(s1, s2, n); } char *strchr(const char *s, int c) { return _strchr(s, c); } char *strcpy(char *dest, const char *src) { return _strcpy(dest, src); } char *strncpy(char *dest, const char *src, long n) { return _strncpy(dest, src, n); } char *strcat(char *dest, const char *app) { return _strcat(dest, app); } char *strrchr(const char *s, int c) { return _strrchr(s, c); } long strtol(const char *nptr, char **endptr, int base) { return _strtol(nptr, endptr, base); } unsigned long strtoul(const char *nptr, char **endptr, int base) { #if CAM_DRYOS return (unsigned long)_strtolx(nptr, endptr, base, 0); #else return _strtoul(nptr, endptr, base); #endif } #if !CAM_DRYOS char *strpbrk(const char *s, const char *accept) { return _strpbrk(s, accept); } #endif //---------------------------------------------------------------------------- long sprintf(char *s, const char *st, ...) { long res; __builtin_va_list va; __builtin_va_start(va, st); res = _vsprintf(s, st, va); __builtin_va_end(va); return res; } // strerror exists on vxworks cams, // but it does about the same thing as this const char *strerror(int en) { #if !CAM_DRYOS static char msg[20]; sprintf(msg,"errno 0x%X",en); return msg; #else (void)en; return "error"; #endif } //---------------------------------------------------------------------------- // Time wrappers unsigned long time(unsigned long *timer) { return _time(timer); } int utime(const char *file, struct utimbuf *newTimes) { #if !CAM_DRYOS return _utime(file, newTimes); #else int res=0; int fd; fd = _open(file, 0, 0); #ifdef CAM_DRYOS_2_3_R39 if (fd>=0) { _close(fd); res=_SetFileTimeStamp(file, newTimes->modtime, newTimes->actime); } #else if (fd>=0) { res=_SetFileTimeStamp(fd, newTimes->modtime, newTimes->actime); _close(fd); } // return value compatibe with utime: ok=0 fail=-1 #endif return (res)?0:-1; #endif } struct tm *localtime(const time_t *_tod) { #if !CAM_DRYOS return _localtime(_tod); #else // for DRYOS cameras do something with this! - sizeof(x[]) must be >= sizeof(struct tm) : 'static int x[9];' static int x[10]; return _LocalTime(_tod, &x); #endif } long strftime(char *s, unsigned long maxsize, const char *format, const struct tm *timp) { return _strftime(s,maxsize,format,timp); } time_t mktime(struct tm *timp) { #if !CAM_DRYOS return _mktime(timp); #else int timp_ext[10]; // struct tm + a ptr _memcpy(timp_ext,timp,9*sizeof(int)); timp_ext[9]=0; long retval = _mktime_ext(&timp_ext); _memcpy(timp,timp_ext,9*sizeof(int)); return retval; #endif } void set_clock(int year, int month, int day, int hour, int minute, int second) { int buf[6]; buf[0] = year; buf[1] = month; buf[2] = day; buf[3] = hour; buf[4] = minute; buf[5] = second; _SetDate(buf); // SetDate sets second, so adjust subsec offset camera_info.tick_count_offset = get_tick_count() % 1000; } //---------------------------------------------------------------------------- // Math wrappers double log(double x) { return __log(x); } double log10(double x) { return __log10(x); } double pow(double x, double y) { return __pow(x, y); } double sqrt(double x) { return __sqrt(x); } // log2(x) = log(x) * (1 / log(2)) double log2(double x) { return (log(x) * ((double)1.44269504088906)); } //---------------------------------------------------------------------------- #ifdef OPT_EXMEM_MALLOC void *exmem_alloc_cached(unsigned int pool_id,unsigned int size,int unk,int unk2) { return _exmem_alloc(pool_id,size,unk,unk2); } #endif void *exmem_alloc_uncached(unsigned int type, unsigned int size, exmem_alloc_info *allocinf) { return _exmem_ualloc(type, size, allocinf); } void exmem_free_uncached(unsigned int type) { _exmem_ufree(type); } void *canon_malloc(long size) { #if CAM_DRYOS return _malloc(size); #else if (_TakeSemaphore(canon_heap_sem,CANON_HEAP_SEM_TIMEOUT)) { return 0; } else { void *r=_malloc(size); _GiveSemaphore(canon_heap_sem); return r; } #endif } void canon_free(void *p) { #if CAM_DRYOS _free(p); #else if (!_TakeSemaphore(canon_heap_sem,CANON_HEAP_SEM_TIMEOUT)) { _free(p); _GiveSemaphore(canon_heap_sem); } #endif } void *umalloc(long size) { #if CAM_DRYOS return _AllocateUncacheableMemory(size); #else if (_TakeSemaphore(canon_heap_sem,CANON_HEAP_SEM_TIMEOUT)) { return 0; } else { void *r=_AllocateUncacheableMemory(size); _GiveSemaphore(canon_heap_sem); return r; } #endif } void ufree(void *p) { #if CAM_DRYOS _FreeUncacheableMemory(p); #else if (!_TakeSemaphore(canon_heap_sem,CANON_HEAP_SEM_TIMEOUT)) { _FreeUncacheableMemory(p); _GiveSemaphore(canon_heap_sem); } #endif } void *memcpy(void *dest, const void *src, long n) { return _memcpy(dest, src, n); } void *memset(void *s, int c, int n) { return _memset(s, c, n); } int memcmp(const void *s1, const void *s2, long n) { return _memcmp(s1, s2, n); } #if !CAM_DRYOS void *memchr(const void *s, int c, int n) { return _memchr(s,c,n); } #endif //---------------------------------------------------------------------------- void GetMemInfo(cam_meminfo *camera_meminfo) { // Use firmware GetMemInfo function to retrieve info about Canon heap memory allocation #if defined(CAM_DRYOS) // Prior to dryos R39 GetMemInfo returns 9 values, after R39 it returns 10 (all but 1 are used in each case) int fw_info[10]; extern void _GetMemInfo(int*); _GetMemInfo(fw_info); #if defined(CAM_DRYOS_2_3_R39) // For newer dryos version copy all 9 used values to CHDK structure camera_meminfo->start_address = fw_info[0]; camera_meminfo->end_address = fw_info[1]; camera_meminfo->total_size = fw_info[2]; camera_meminfo->allocated_size = fw_info[3]; camera_meminfo->allocated_peak = fw_info[4]; camera_meminfo->allocated_count = fw_info[5]; camera_meminfo->free_size = fw_info[6]; camera_meminfo->free_block_max_size = fw_info[7]; camera_meminfo->free_block_count = fw_info[8]; #else // For older dryos version copy 8 used values to CHDK structure and calculate missing value camera_meminfo->start_address = fw_info[0]; camera_meminfo->end_address = fw_info[0] + fw_info[1]; camera_meminfo->total_size = fw_info[1]; camera_meminfo->allocated_size = fw_info[2]; camera_meminfo->allocated_peak = fw_info[3]; camera_meminfo->allocated_count = fw_info[4]; camera_meminfo->free_size = fw_info[5]; camera_meminfo->free_block_max_size = fw_info[6]; camera_meminfo->free_block_count = fw_info[7]; #endif #else // vxworks extern int sys_mempart_id; // -1 for invalid memset(camera_meminfo,0xFF,sizeof(cam_meminfo)); if(!_TakeSemaphore(canon_heap_sem,CANON_HEAP_SEM_TIMEOUT)) { #ifdef CAM_NO_MEMPARTINFO camera_meminfo->free_block_max_size = _memPartFindMax(sys_mempart_id); #else int fw_info[5]; _memPartInfoGet(sys_mempart_id,fw_info); // TODO we could fill in start address from _start + MEMISOSIZE, if chdk not in exmem // these are guessed, look reasonable on a540 camera_meminfo->free_size = fw_info[0]; camera_meminfo->free_block_count = fw_info[1]; camera_meminfo->free_block_max_size = fw_info[2]; camera_meminfo->allocated_size = fw_info[3]; camera_meminfo->allocated_count = fw_info[4]; #endif _GiveSemaphore(canon_heap_sem); } #endif } //---------------------------------------------------------------------------- int rand(void) { return _rand(); } void *srand(unsigned int seed) { return _srand(seed); } void qsort(void *__base, int __nelem, int __size, int (*__cmp)(const void *__e1, const void *__e2)) { _qsort(__base, __nelem, __size, __cmp); } static int shutdown_disabled = 0; void disable_shutdown() { if (!shutdown_disabled) { _LockMainPower(); shutdown_disabled = 1; } } void enable_shutdown() { if (shutdown_disabled) { _UnlockMainPower(); shutdown_disabled = 0; } } void camera_shutdown_in_a_second(void) { int i; _SetAutoShutdownTime(1); // 1 sec for (i=0;i<200;i++) _UnlockMainPower(); // set power unlock counter to 200 or more, because every keyboard function call try to lock power again ( if "Disable LCD off" menu is "alt" or "script"). } void EnterToCompensationEVF(void) { _EnterToCompensationEVF(); } void ExitFromCompensationEVF() { _ExitFromCompensationEVF(); } void TurnOnBackLight(void) { _TurnOnBackLight(); } void TurnOffBackLight(void) { _TurnOffBackLight(); } extern void gui_set_need_restore(); void TurnOnDisplay(void) { _TurnOnDisplay(); // required to re-draw the canon and CHDK UI after re-enabling display gui_set_need_restore() ; } void TurnOffDisplay(void) { _TurnOffDisplay(); } void DoAELock(void) { if (!camera_info.state.mode_play) { _DoAELock(); } } void UnlockAE(void) { if (!camera_info.state.mode_play) { _UnlockAE(); } } void DoAFLock(void) { if (!camera_info.state.mode_play) { int af_lock=1; _DoAFLock(); set_property_case(PROPCASE_AF_LOCK,&af_lock,sizeof(af_lock)); } } void UnlockAF(void) { if (!camera_info.state.mode_play) { int af_lock=0; _UnlockAF(); set_property_case(PROPCASE_AF_LOCK,&af_lock,sizeof(af_lock)); } } int EngDrvRead(int gpio_reg) { return _EngDrvRead(gpio_reg); } #if CAM_MULTIPART #define SECTOR_SIZE 512 static char *mbr_buf=(void*)0; static unsigned long drive_sectors; int is_mbr_loaded() { return (mbr_buf == (void*)0) ? 0 : 1; } #ifndef CAM_DRYOS int mbr_read(char* mbr_sector, unsigned long drive_total_sectors, unsigned long *part_start_sector, unsigned long *part_length){ // return value: 1 - success, 0 - fail // called only in VxWorks int offset=0x10; // points to partition #2 int valid; if ((mbr_sector[0x1FE]!=0x55) || (mbr_sector[0x1FF]!=0xAA)) return 0; // signature check mbr_buf=_AllocateUncacheableMemory(SECTOR_SIZE); _memcpy(mbr_buf,mbr_sector,SECTOR_SIZE); drive_sectors=drive_total_sectors; while(offset>=0) { *part_start_sector=(*(unsigned short*)(mbr_sector+offset+0x1C8)<<16) | *(unsigned short*)(mbr_sector+offset+0x1C6); *part_length=(*(unsigned short*)(mbr_sector+offset+0x1CC)<<16) | *(unsigned short*)(mbr_sector+offset+0x1CA); valid= (*part_start_sector) && (*part_length) && (*part_start_sector<=drive_total_sectors) && (*part_start_sector+*part_length<=drive_total_sectors) && ((mbr_sector[offset+0x1BE]==0) || (mbr_sector[offset+0x1BE]==0x80)); // status: 0x80 (active) or 0 (non-active) if (valid && ((mbr_sector[0x1C2+offset]==0x0B) || (mbr_sector[0x1C2+offset]==0x0C))) break; // FAT32 secondary partition offset-=0x10; } return valid; } #else int mbr_read_dryos(unsigned long drive_total_sectors, char* mbr_sector ){ // Called only in DRYOS mbr_buf=_AllocateUncacheableMemory(SECTOR_SIZE); _memcpy(mbr_buf,mbr_sector,SECTOR_SIZE); drive_sectors=drive_total_sectors; return drive_total_sectors; } #endif int get_part_count(void) { unsigned long part_start_sector, part_length; char part_status, part_type; int i; int count=0; if (is_mbr_loaded()) { for (i=0; i<=3;i++) { part_start_sector=(*(unsigned short*)(mbr_buf+i*16+0x1C8)<<16) | *(unsigned short*)(mbr_buf+i*16+0x1C6); part_length=(*(unsigned short*)(mbr_buf+i*16+0x1CC)<<16) | *(unsigned short*)(mbr_buf+i*16+0x1CA); part_status=mbr_buf[i*16+0x1BE]; part_type=mbr_buf[0x1C2+i*16]; if ( part_start_sector && part_length && part_type && ((part_status==0) || (part_status==0x80)) ) count++; } } return count; } int get_part_type() { int partType = 0x00; if (is_mbr_loaded()) { partType=mbr_buf[0x1C2+(get_active_partition()-1)*16]; } return partType; } static int boot_partition = 0; static int partition_changed = 0; int is_partition_changed() { return partition_changed; } int swap_partitions(int new_partition) { if (is_mbr_loaded()) { int i,j,p; char c; int partition_count = get_part_count(); int active_partition = get_active_partition(); if(!boot_partition) { boot_partition = active_partition; } // wrong input if( new_partition > partition_count || new_partition <= 0 ) { return 0; } partition_changed = (new_partition==boot_partition)?0:1; // rotate partitions till new_partition is found for(j=0;j>8; mbr_buf[0x1BE + 10]=start>>16; mbr_buf[0x1BE + 11]=start>>24; mbr_buf[0x1BE + 12]=length; mbr_buf[0x1BE + 13]=length>>8; mbr_buf[0x1BE + 14]=length>>16; mbr_buf[0x1BE + 15]=length>>24; start=start+length; length=drive_sectors-start-1; type=0x0B; //FAT32 primary; mbr_buf[0x1CE + 4]=type; mbr_buf[0x1CE + 8]=start; mbr_buf[0x1CE + 9]=start>>8; mbr_buf[0x1CE + 10]=start>>16; mbr_buf[0x1CE + 11]=start>>24; mbr_buf[0x1CE + 12]=length; mbr_buf[0x1CE + 13]=length>>8; mbr_buf[0x1CE + 14]=length>>16; mbr_buf[0x1CE + 15]=length>>24; mbr_buf[0x1FE]=0x55; mbr_buf[0x1FF]=0xAA; // signature; _WriteSDCard(0,0,1,mbr_buf); } } #else // Dummy for scripts if not implemented in camera int swap_partitions(__attribute__ ((unused))int new_partition) { return 0; } int get_part_count(void) { return 1; } int get_part_type() { return 0; } unsigned char get_active_partition(void) { return 1; } int is_partition_changed() { return 0; } #endif int mute_on_zoom(int x){ static int old_busy=0; int busy=zoom_busy||focus_busy; if (old_busy!=busy) { if (busy) { #if CAM_CAN_MUTE_MICROPHONE if (conf.mute_on_zoom) _TurnOffMic(); #endif } else { #if CAM_CAN_MUTE_MICROPHONE if (conf.mute_on_zoom) _TurnOnMic(); #endif #if CAM_EV_IN_VIDEO if (get_ev_video_avail()) set_ev_video_avail(0); #endif } old_busy=busy; } return x; // preserve R0 if called from assembler } #if CAM_AF_SCAN_DURING_VIDEO_RECORD void MakeAFScan(void){ int a=0, save; if (zoom_busy || focus_busy) return; save=some_flag_for_af_scan; some_flag_for_af_scan=0; #if CAM_AF_SCAN_DURING_VIDEO_RECORD == 2 parameter_for_af_scan=3; #endif _MakeAFScan(&a, 3); some_flag_for_af_scan=save; #if CAM_RESET_AEL_AFTER_VIDEO_AF int ae_lock; get_property_case(PROPCASE_AE_LOCK,&ae_lock,sizeof(ae_lock)); if (ae_lock == 0) // AE not locked so ensure it is unlocked after re-focus _ExpCtrlTool_StartContiAE(0,0); else // AE locked before so re-lock after _ExpCtrlTool_StopContiAE(0,0); #else _ExpCtrlTool_StartContiAE(0,0); #endif } #endif long __attribute__((weak)) get_jogdial_direction(void) { return 0; } void __attribute__((weak)) JogDial_CW(void) {} void __attribute__((weak)) JogDial_CCW(void) {} #if defined (DNG_EXT_FROM) #define DNG_EXT_TO ".DNG" typedef int(*p_some_f)(char*, int); extern p_some_f some_f_for_dng; // camera variable! extern char* second_ext_for_dng; // camera variable! p_some_f default_some_f; char * default_second_ext; int my_some_f(char *s, int x){ char *f; f=strstr(s, DNG_EXT_FROM); if (f) _memcpy(f, DNG_EXT_TO, sizeof(DNG_EXT_TO)-1); return default_some_f(s, x); } void save_ext_for_dng(void){ default_some_f=some_f_for_dng; default_second_ext=second_ext_for_dng; } void change_ext_to_dng(void){ some_f_for_dng=my_some_f; second_ext_for_dng=DNG_EXT_TO; } void change_ext_to_default(void){ some_f_for_dng=default_some_f; second_ext_for_dng=default_second_ext; } #endif #if !CAM_DRYOS static long drv_struct[16]; #endif long dh_err() { return -1; } #if !CAM_DRYOS void drv_self_hide() { long drvnum; drvnum = _iosDrvInstall(dh_err,dh_err,dh_err,dh_err,dh_err,dh_err,dh_err); if (drvnum >= 0) _iosDevAdd(drv_struct, "A/DISKBOOT.BIN", drvnum); } void drv_self_unhide() { _iosDevDelete(drv_struct); } #endif int apex2us(int apex_tv){ #if CAM_EXT_TV_RANGE /* Extended Tv, by barberofcivil, http://chdk.setepontos.com/index.php/topic,4392.0.html Explanation by reyalP: In every port, the original shutter overrides (as opposed to super long exposure) worked by setting the propcase values at some point after auto-exposure has happened (except in manual modes, where the manual control propcases may be used instead). The Canon code previously took these values unchanged for short exposures. In newer cameras, like on the SX10 / SD980, the value is changed, apparently some time after it has been retrieved from the propcase. We know this is the case, because the propcase value itself doesn't get clamped to the allowed range (if it did, barberofcivil's code wouldn't work). */ short tv; tv = shooting_get_tv96(); if (tv<-576 || tv!=apex_tv) return 1000000.0*pow(2.0, -tv/96.0); else return _apex2us(apex_tv); #else return 0; #endif } void PostLogicalEventForNotPowerType(unsigned id, unsigned x) { _PostLogicalEventForNotPowerType(id,x); } void PostLogicalEventToUI(unsigned id, unsigned x) { _PostLogicalEventToUI(id,x); } void SetLogicalEventActive(unsigned id, unsigned state) { _SetLogicalEventActive(id, state); } void SetScriptMode(unsigned mode) { _SetScriptMode(mode); } // TODO this belongs lib.c, but not all cameras include it // same as bitmap width for most cameras, override in platform/sub/lib.c as needed int __attribute__((weak)) vid_get_viewport_width() { return camera_screen.width; } // Physical width of viewport row in bytes int __attribute__((weak)) vid_get_viewport_byte_width() { return 720 * 6 / 4; // For most cameras viewport is 720 pixels wide, each group of 4 pixels uses 6 bytes (UYVYYY) } // Y multiplier for cameras with 480 pixel high viewports (CHDK code assumes 240) int __attribute__((weak)) vid_get_viewport_yscale() { return 1; // For most cameras viewport is 240 pixels high } // viewport x offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay) int __attribute__((weak)) vid_get_viewport_xoffset() { return 0; } // viewport y offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay) int __attribute__((weak)) vid_get_viewport_yoffset() { return 0; } // viewport display x offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay) int __attribute__((weak)) vid_get_viewport_display_xoffset() { return vid_get_viewport_xoffset(); } // viewport display y offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay) int __attribute__((weak)) vid_get_viewport_display_yoffset() { return vid_get_viewport_yoffset(); } // format of live view viewport #ifndef THUMB_FW int vid_get_viewport_type() { return LV_FB_YUV8; } // D6 cameras must define #endif // for cameras with two (or more?) RAW buffers this can be used to speed up DNG creation by // calling reverse_bytes_order only once. Override in platform/sub/lib.c char __attribute__((weak)) *hook_alt_raw_image_addr() { return hook_raw_image_addr(); } void __attribute__((weak)) vid_turn_off_updates() { } void __attribute__((weak)) vid_turn_on_updates() { } // use _GetFocusLensSubjectDistance for this on dryos, vx functions are basically equivlent // not used in CHDK currently for either OS #ifdef CAM_DRYOS long __attribute__((weak)) _GetCurrentTargetDistance() { return _GetFocusLensSubjectDistance(); } #endif int add_ptp_handler(int opcode, ptp_handler handler, int unknown) { #ifdef CAM_CHDK_PTP return _add_ptp_handler(opcode,handler,unknown); #else return 0; #endif } #ifdef CAM_PTP_USE_NATIVE_BUFFER int get_ptp_file_buf_size(void) { return _get_ptp_buf_size(CAM_PTP_FILE_BUFFER_ID); } char *get_ptp_file_buf(void) { return _get_ptp_file_buf(); } #endif int CreateTask (const char *name, int prio, int stack_size, void *entry) { return _CreateTask(name, prio, stack_size, entry, 0); } void ExitTask() { _ExitTask(); } // TODO not in sigs for vx yet #ifndef CAM_DRYOS void __attribute__((weak)) _reboot_fw_update(__attribute__ ((unused))const char *fw_update) { return; } #endif #ifdef CAM_PTP_SCREEN_UNLOCK_EVENT // function to take the camera out of the black screen mode // triggered by ptp GetObjectHandles static void do_ptp_screen_unlock(void) { extern int cameracon_state; int t; // if in a transition state, wait up to 500ms for it to change for(t = 0; cameracon_state > 4 && t < 50; t++) { msleep(10); } // if in "black screen" ptp state, send event to switch to regular playback if(cameracon_state == 3) { PostLogicalEventToUI(CAM_PTP_SCREEN_UNLOCK_EVENTID,0); } // wait for state change triggered by event to complete for(t = 0; cameracon_state != 2 && t < 100; t++) { msleep(10); } } #endif #ifdef CAM_DRYOS int __attribute__((weak)) switch_mode_usb(int mode) { #ifdef CAM_CHDK_PTP if ( mode == 0 ) { _Rec2PB(-1); _set_control_event(0x80000000|CAM_USB_EVENTID); } else if ( mode == 1 ) { _set_control_event(CAM_USB_EVENTID); #ifdef CAM_PTP_SCREEN_UNLOCK_EVENT do_ptp_screen_unlock(); #endif _PB2Rec(); } else return 0; return 1; #else return 0; #endif // CAM_CHDK_PTP } #else // vxworks // this doesn't need any special functions so it's defined even without CHDK_CAM_PTP int __attribute__((weak)) switch_mode_usb(int mode) { if ( mode == 0 ) { // TODO should we revert scriptmode and/or levent? seems to work without levent_set_play(); } else if ( mode == 1 ) { #ifdef CAM_USB_EVENTID_VXWORKS _SetScriptMode(1); // needed to override event _SetLogicalEventActive(CAM_USB_EVENTID_VXWORKS,0); // set levent "ConnectUSBCable" inactive #endif #ifdef CAM_PTP_SCREEN_UNLOCK_EVENT do_ptp_screen_unlock(); #endif levent_set_record(); } else return 0; return 1; } #endif // vxworks /* // this wrapper isn't currently needed // 7 calls functions and sets some MMIOs, but doesn't disable caches and actually restart // 3 skips one function call on some cameras, but does restart void Restart(unsigned option) { _Restart(option); } */ unsigned char SetFileAttributes(const char* fn, unsigned char attr) { #ifdef CAM_DRYOS_2_3_R39 return _SetFileAttributes(fn, attr); #else int fd; unsigned char ret = -1; fd = open(fn, 0, 0); if( fd ) { _SetFileAttributes(fd, attr); close(fd); ret = attr; } return ret; #endif } // Default implementation of PTP live view functions. // Override as needed for camera specific variations (see G12/SX30/IXUS310/SX130IS for working examples) int __attribute__((weak)) vid_get_viewport_display_xoffset_proper() { return vid_get_viewport_display_xoffset()*2; } int __attribute__((weak)) vid_get_viewport_display_yoffset_proper() { return vid_get_viewport_display_yoffset(); } int __attribute__((weak)) vid_get_viewport_buffer_width_proper() { return 720; } #ifdef THUMB_FW int __attribute__((weak)) vid_get_viewport_width_proper() { return vid_get_viewport_width(); } int __attribute__((weak)) vid_get_viewport_height_proper() { return vid_get_viewport_height(); } #else int __attribute__((weak)) vid_get_viewport_width_proper() { return vid_get_viewport_width()*2; } int __attribute__((weak)) vid_get_viewport_height_proper() { return 240; } #endif int __attribute__((weak)) vid_get_viewport_fullscreen_height() { return 240; } int __attribute__((weak)) vid_get_viewport_fullscreen_width() { return vid_get_viewport_buffer_width_proper(); } int __attribute__((weak)) vid_get_palette_type() { return 0; } // 0 = no palette into, 1 = 16 x 4 byte AYUV values, // 2 = 16 x 4 byte AYUV (A = 0..3), 3 = 256 x 4 byte AYUV (A = 0..3) int __attribute__((weak)) vid_get_palette_size() { return 0; } int __attribute__((weak)) vid_get_aspect_ratio() { return 0; } // 0 = 4:3, 1 = 16:9 LCD Aspect Ratio, 2 = 3:2 void __attribute__((weak)) *vid_get_bitmap_active_buffer() { return vid_get_bitmap_fb(); // *** does not get the active buffer! (override if active buffer can be determined) } void __attribute__((weak)) *vid_get_bitmap_active_palette() { return 0; // return no palette info unless overridden } // Get active viewport buffer address based on PLAY/REC mode. // Try to use 'live' buffer in REC mode if vid_get_viewport_live_fb is implemented // can return NULL in plaback mode, if a video is selected void *vid_get_viewport_active_buffer() { void *p; if (camera_info.state.mode_play) { p = vid_get_viewport_fb_d(); } else { p = vid_get_viewport_live_fb(); if ( !p ) { p = vid_get_viewport_fb(); } } return p; } /* debug logging function that can be sent to various places body is ifdef'd inside the body to allow exporting to modules eventproc version may require System.Create()/SystemEventInit first */ #ifdef DEBUG_LOGGING void dbg_printf(char *fmt,...) { char s[256]; __builtin_va_list va; __builtin_va_start(va, fmt); _vsprintf(s, fmt, va); __builtin_va_end(va); // stdout - for use with uart redirection _ExecuteEventProcedure("Printf",s); // camera log - will show up in crash dumps, or in stdout on ShowCameraLog // length limited, asserts if too long //s[59]=0; //_LogCameraEvent(0x20,s); // file /* FILE *f=fopen("A/DBGPRINT.LOG","ab"); if(!f) { return; } fwrite(s,strlen(s),1,f); fclose(f); */ } #endif #ifdef CAM_MISSING_RAND /* Some cameras does not have srand()/rand() functions in firmware, and should be aded here. E.G. a810/a2300 */ static unsigned int random_variable; void *_srand(unsigned int seed) { random_variable = seed; return (void *) &random_variable; } int _rand(void) { int value; value = random_variable*0x41C64E6D+0x3039; random_variable = value; value = (0x7FFF & (value>>0x10)); return value; }; #endif // USB remote high speed timer for pulse width measurement and pulse counting extern int _SetHPTimerAfterNow(int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int ); extern int _CancelHPTimer(int); extern int usb_HPtimer_bad(int, int); extern int usb_HPtimer_good(int, int); int usb_HPtimer_handle=0; static int ARM_usb_HPtimer_good(int time, int interval) { return usb_HPtimer_good(time, interval); } static int ARM_usb_HPtimer_bad(int time, int interval) { return usb_HPtimer_bad(time, interval); } int start_usb_HPtimer(int interval) // return 0 if timer already running or error, 1 if successful { #ifdef CAM_REMOTE_USB_HIGHSPEED if ( usb_HPtimer_handle == 0 ) { if(interval < CAM_REMOTE_HIGHSPEED_LIMIT) interval=CAM_REMOTE_HIGHSPEED_LIMIT; usb_HPtimer_handle = _SetHPTimerAfterNow(interval,ARM_usb_HPtimer_good,ARM_usb_HPtimer_bad,interval); if (!(usb_HPtimer_handle & 0x01)) return 1 ; usb_HPtimer_handle = 0 ; } #endif return 0; } int stop_usb_HPtimer() { #ifdef CAM_REMOTE_USB_HIGHSPEED if( usb_HPtimer_handle ) { _CancelHPTimer(usb_HPtimer_handle); usb_HPtimer_handle = 0 ; return 1 ; } #endif return 0; } // HP timer functions, callbacks need to be ARM on VxWorks int SetHPTimerAfterNow(int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int param) { return _SetHPTimerAfterNow(delay,good_cb,bad_cb,param); } int CancelHPTimer(int handle) { return _CancelHPTimer(handle); } // Override HDMI power on in rec mode for using HDMI Hotplug detect as remote // note does not disable power if remote turned off or channel changed // May want to add support for controlling independent of remote as output signal #ifdef CAM_REMOTE_HDMI_POWER_OVERRIDE extern void _EnableHDMIPower(); void update_hdmi_power_override() { static int oldhdmistate = -1; if ((camera_info.state.mode_rec == 1) && conf.remote_enable && (conf.remote_input_channel == REMOTE_INPUT_HDMI_HPD)) { /* if switched to shooting mode and remote using HDMI hotplug is enabled, switch on HDMI Power */ /* just do it once on every change because it needs i2c communication depending on HDMI tranceiver */ if (oldhdmistate != 1) { _EnableHDMIPower(); } oldhdmistate = 1; } else { oldhdmistate = 0; } } #endif // disable camera error(s), E32 is the only error that can be handled at the moment (on newer 'IS' cameras) #if (OPT_DISABLE_CAM_ERROR) #warning OPT_DISABLE_CAM_ERROR enabled void DisableCamError(void) { extern void _DisableISDriveError(void); _DisableISDriveError(); } #endif //--------------------------------------------------------------- // Semaphore & Assert void DebugAssert(char *err, int line) { #if CAM_3ARG_DebugAssert extern void _DebugAssert(int, char*, int); _DebugAssert(0, err, line); #else extern void _DebugAssert(char*, int); _DebugAssert(err, line); #endif } int CreateBinarySemaphore(char *name, int init) { extern int _CreateBinarySemaphore(char*, int); return _CreateBinarySemaphore(name, init); } int TakeSemaphore(int sem, int timeout) { return _TakeSemaphore(sem, timeout); } void GiveSemaphore(int sem) { _GiveSemaphore(sem); } void DeleteSemaphore(int sem) { _DeleteSemaphore(sem); } //--------------------------------------------------------------- // Video out #ifdef CAM_UNLOCK_ANALOG_AV_IN_REC void SetVideoOutType(int x) { extern void _SetVideoOutType(int); _TurnOffDisplay(); _SetVideoOutType(x); _TurnOnDisplay(); } int GetVideoOutType(void) { extern int _GetVideoOutType(void); return _GetVideoOutType(); } #endif //--------------------------------------------------------------- #ifdef CAM_HAS_GPS void GPS_UpdateData() { extern void _GPS_UpdateData(); _GPS_UpdateData(); } #endif //---------------------------------------------------------------