root/platform/generic/wrappers.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. isdigit
  2. isspace
  3. isalpha
  4. isupper
  5. islower
  6. ispunct
  7. isxdigit
  8. tolower
  9. toupper
  10. submenu_sort_arm
  11. msleep
  12. task_lock
  13. task_unlock
  14. task_name
  15. task_id_list_get
  16. get_property_case
  17. set_property_case
  18. get_parameter_size
  19. get_parameter_data
  20. set_parameter_data
  21. get_uiprop_value
  22. mark_filesystem_bootable
  23. vid_bitmap_refresh
  24. lens_get_zoom_pos
  25. lens_get_zoom_point
  26. lens_set_zoom_point
  27. lens_set_zoom_speed
  28. lens_set_focus_pos
  29. play_sound
  30. stat_get_vbatt
  31. GetAdChValue
  32. get_battery_temp
  33. get_ccd_temp
  34. get_optical_temp
  35. get_tick_count
  36. PutInNdFilter
  37. PutOutNdFilter
  38. shooting_get_nd_value_ev96
  39. shooting_get_nd_current_ev96
  40. shooting_get_current_tv96
  41. shooting_get_current_av96
  42. IsStrobeChargeCompleted
  43. SetCurrentCaptureModeType
  44. GetUsableMinAv
  45. GetUsableMaxAv
  46. UnsetZoomForMovie
  47. MoveIrisWithAv
  48. ExpCtrlTool_StartContiAE
  49. ExpCtrlTool_StopContiAE
  50. SetAE_ShutterSpeed
  51. takeFileIOSemaphore
  52. open
  53. close
  54. write
  55. read
  56. lseek
  57. mkdir
  58. mkdir_if_not_exist
  59. remove
  60. fw_closedir
  61. get_fstype
  62. fw_opendir
  63. fw_readdir
  64. fw_opendir
  65. fw_readdir
  66. stat
  67. fopen
  68. fclose
  69. fread
  70. fwrite
  71. fseek
  72. feof
  73. fflush
  74. fgets
  75. rename
  76. GetFreeCardSpaceKb
  77. GetTotalCardSpaceKb
  78. errnoOfTaskGet
  79. strlen
  80. strcmp
  81. strncmp
  82. strchr
  83. strcpy
  84. strncpy
  85. strcat
  86. strrchr
  87. strtol
  88. strtoul
  89. strpbrk
  90. sprintf
  91. strerror
  92. time
  93. utime
  94. localtime
  95. strftime
  96. mktime
  97. _log
  98. _log10
  99. _pow
  100. _sqrt
  101. exmem_alloc
  102. canon_malloc
  103. canon_free
  104. umalloc
  105. ufree
  106. memcpy
  107. memset
  108. memcmp
  109. memchr
  110. GetMemInfo
  111. rand
  112. srand
  113. qsort
  114. disable_shutdown
  115. enable_shutdown
  116. camera_shutdown_in_a_second
  117. EnterToCompensationEVF
  118. ExitFromCompensationEVF
  119. TurnOnBackLight
  120. TurnOffBackLight
  121. TurnOnDisplay
  122. TurnOffDisplay
  123. DoAELock
  124. UnlockAE
  125. DoAFLock
  126. UnlockAF
  127. EngDrvRead
  128. is_mbr_loaded
  129. mbr_read
  130. mbr_read_dryos
  131. get_part_count
  132. get_part_type
  133. is_partition_changed
  134. swap_partitions
  135. get_active_partition
  136. create_partitions
  137. swap_partitions
  138. get_part_count
  139. get_part_type
  140. get_active_partition
  141. is_partition_changed
  142. mute_on_zoom
  143. MakeAFScan
  144. get_jogdial_direction
  145. JogDial_CW
  146. JogDial_CCW
  147. my_some_f
  148. save_ext_for_dng
  149. change_ext_to_dng
  150. change_ext_to_default
  151. dh_err
  152. drv_self_hide
  153. drv_self_unhide
  154. apex2us
  155. PostLogicalEventForNotPowerType
  156. PostLogicalEventToUI
  157. SetLogicalEventActive
  158. SetScriptMode
  159. vid_get_viewport_width
  160. vid_get_viewport_byte_width
  161. vid_get_viewport_yscale
  162. vid_get_viewport_xoffset
  163. vid_get_viewport_yoffset
  164. vid_get_viewport_display_xoffset
  165. vid_get_viewport_display_yoffset
  166. vid_get_viewport_type
  167. hook_alt_raw_image_addr
  168. vid_turn_off_updates
  169. vid_turn_on_updates
  170. _GetCurrentTargetDistance
  171. add_ptp_handler
  172. CreateTask
  173. ExitTask
  174. _reboot_fw_update
  175. switch_mode_usb
  176. switch_mode_usb
  177. SetFileAttributes
  178. vid_get_viewport_display_xoffset_proper
  179. vid_get_viewport_display_yoffset_proper
  180. vid_get_viewport_buffer_width_proper
  181. vid_get_viewport_width_proper
  182. vid_get_viewport_height_proper
  183. vid_get_viewport_fullscreen_height
  184. vid_get_viewport_fullscreen_width
  185. vid_get_palette_type
  186. vid_get_palette_size
  187. vid_get_aspect_ratio
  188. vid_get_bitmap_active_buffer
  189. vid_get_bitmap_active_palette
  190. vid_get_viewport_active_buffer
  191. dbg_printf
  192. _srand
  193. _rand
  194. ARM_usb_HPtimer_good
  195. ARM_usb_HPtimer_bad
  196. start_usb_HPtimer
  197. stop_usb_HPtimer
  198. SetHPTimerAfterNow
  199. CancelHPTimer
  200. update_hdmi_power_override
  201. DisableCamError
  202. DebugAssert
  203. CreateBinarySemaphore
  204. TakeSemaphore
  205. GiveSemaphore

   1 #include "camera.h"
   2 #include "lolevel.h"
   3 #include "platform.h"
   4 #include "raw_buffer.h"
   5 #include "conf.h"
   6 #include "math.h"
   7 #include "levent.h"
   8 #include "stdlib.h"
   9 #include "ptp_chdk.h"
  10 #include "live_view.h"
  11 #include "usb_remote.h"
  12 
  13 //----------------------------------------------------------------------------
  14 // Char Wrappers (VxWorks - ARM stubs)
  15 
  16 #if !CAM_DRYOS
  17 
  18 int isdigit(int c) { return _isdigit(c); }
  19 int isspace(int c) { return _isspace(c); }
  20 int isalpha(int c) { return _isalpha(c); }
  21 int isupper(int c) { return _isupper(c); }
  22 int islower(int c) { return _islower(c); }
  23 int ispunct(int c) { return _ispunct(c); }
  24 int isxdigit(int c) { return _isxdigit(c); }
  25 
  26 int tolower(int c) { return _tolower(c); }
  27 int toupper(int c) { return _toupper(c); }
  28 
  29 #endif
  30 
  31 //----------------------------------------------------------------------------
  32 
  33 int submenu_sort_arm(const void* v1, const void* v2)
  34 {
  35     extern int submenu_sort(const void* v1, const void* v2);
  36     return submenu_sort(v1, v2);
  37 }
  38 
  39 //----------------------------------------------------------------------------
  40 
  41 void msleep(long msec)
  42 {
  43     _SleepTask(msec);
  44 }
  45 
  46 #ifndef CAM_DRYOS
  47 long task_lock()
  48 {
  49     return _taskLock();
  50 }
  51 
  52 long task_unlock()
  53 {
  54     return _taskUnlock();
  55 }
  56 
  57 const char *task_name(int id)
  58 {
  59     return _taskName(id);
  60 }
  61 
  62 int task_id_list_get(int *idlist,int size)
  63 {
  64     return _taskIdListGet(idlist,size);
  65 }
  66 #endif
  67 
  68 long get_property_case(long id, void *buf, long bufsize)
  69 {
  70 // workaround for missing PROPCASE_SHOOTING
  71 #if CAM_PROPSET == 7 || CAM_PROPSET == 9 || CAM_PROPSET == 10 || CAM_PROPSET == 11
  72     if(id==PROPCASE_SHOOTING) {
  73         int r=_GetPropertyCase(PROPCASE_SHOOTING_STATE, buf, bufsize);
  74         // 1 50ms after half press, 2 after exp hook, 3 while shooting
  75         // propset 6 has similar procase id 351, goes 3->0 when get_shooting goes false
  76         // propset 4 and 5 id 352 is similar but only goes to 2
  77         // (4 per https://chdk.setepontos.com/index.php?topic=11604.msg113712#msg113712)
  78         if(*(char *)buf > 1) {
  79             *(char *)buf = 1;
  80         } else {
  81             *(char *)buf = 0;
  82         }
  83         return r;
  84     }
  85 #endif
  86     return _GetPropertyCase(id, buf, bufsize);
  87 }
  88 
  89 long set_property_case(long id, void *buf, long bufsize)
  90 {
  91     // ignore set on fake prop
  92 #if CAM_PROPSET == 7 || CAM_PROPSET == 9 || CAM_PROPSET == 10 || CAM_PROPSET == 11
  93     if(id==PROPCASE_SHOOTING) {
  94         return 0;
  95     }
  96 #endif
  97 
  98     return _SetPropertyCase(id, buf, bufsize);
  99 }
 100 
 101 // FlashParamsTable entries point to this structure
 102 #if CAM_FLASHPARAMS_VERSION == 2
 103 // ixus30_sd200, ixus40_sd300
 104 typedef struct
 105 {
 106     short   unk1;
 107     short   unk2;
 108     void*   data;   // Pointer to param data
 109     short   size;   // param size
 110     short   unk3;
 111     int     unk4;
 112     short   unk5;
 113     short   unk6;
 114 } flashParam;
 115 #else
 116 // version 3 (every camera from 2005 on)
 117 typedef struct
 118 {
 119     void*   data;   // Pointer to param data
 120     short   unk1;
 121     short   size;   // param size
 122     short   unk2;
 123     short   unk3;
 124     short   unk4;
 125     char    unk5;
 126     char    unk6;
 127 } flashParam;
 128 #endif // CAM_FLASHPARAMS_VERSION
 129 
 130 short get_parameter_size(long id)
 131 {
 132     extern flashParam* FlashParamsTable[];
 133 
 134     if ((id >= 0) && (id < get_flash_params_count()))
 135         return FlashParamsTable[id]->size;
 136 
 137     return 0;
 138 }
 139 
 140 long get_parameter_data(long id, void *buf, long bufsize)
 141 {
 142     return _GetParameterData(id|PARAMETER_DATA_FLAG, buf, bufsize);
 143 }
 144 
 145 long set_parameter_data(long id, void *buf, long bufsize)
 146 {
 147     return _SetParameterData(id|PARAMETER_DATA_FLAG, buf, bufsize);
 148 }
 149 
 150 short __attribute__((weak)) get_uiprop_value(unsigned long id)
 151 {
 152     // avoid asserts: return 0 if id is above limit
 153     if (id >= uiprop_count)
 154         return 0;
 155     return _PTM_GetCurrentItem(id|0x8000);
 156 }
 157 
 158 void mark_filesystem_bootable()
 159 {
 160 #ifdef  CAM_DRYOS_2_3_R47
 161     // DryOS release 47 (2011) no longer has the UpdateMBROnFlash function to write the master boot record on
 162     // the SD card. Instead it has seperate functions for writing the 'BOOTDISK' and 'SCRIPT' signatures to
 163     // the MBR. The firmware function also takes care of writing the bootdisk signature to the correct location
 164     // for FAT32 formatted cards.
 165     _MakeSDCardBootable(0);
 166 #else
 167     _UpdateMBROnFlash(0, 0x40, "BOOTDISK");
 168 #endif
 169 }
 170 
 171 void __attribute__((weak)) vid_bitmap_refresh()
 172 {
 173     _RefreshPhysicalScreen(1);
 174 }
 175 
 176 long lens_get_zoom_pos()
 177 {
 178     return _GetZoomLensCurrentPosition();
 179 }
 180 
 181 long lens_get_zoom_point()
 182 {
 183     return _GetZoomLensCurrentPoint();
 184 }
 185 
 186 void lens_set_zoom_point(long newpt)
 187 {
 188     if (newpt < 0) {
 189         newpt = 0;
 190     } else if (newpt >= zoom_points) {
 191         newpt = zoom_points-1;
 192     }
 193 
 194 #if defined(CAM_USE_ALT_SET_ZOOM_POINT)
 195 
 196         if (lens_get_zoom_point() != newpt)
 197         {
 198                 int digizoom_pos;
 199                 get_property_case(PROPCASE_DIGITAL_ZOOM_POSITION,&digizoom_pos,sizeof(digizoom_pos));
 200                 // check current digital zoom mode & state
 201                 // state == 1 && mode == 0 --> Digital Zoom Standard
 202                 if ((shooting_get_digital_zoom_state() == 1) && (shooting_get_digital_zoom_mode() == 0) && (digizoom_pos != 0))
 203                 {
 204                         // reset digital zoom in case camera is in this zoom range
 205                         extern void _PT_MoveDigitalZoomToWide();
 206                         _PT_MoveDigitalZoomToWide();
 207                 }
 208 
 209   #if defined(CAM_USE_ALT_PT_MoveOpticalZoomAt)
 210                 // SX30 - _MoveZoomLensWithPoint crashes camera
 211                 // _PT_MoveOpticalZoomAt works, and updates PROPCASE_OPTICAL_ZOOM_POSITION; but doesn't wait for zoom to finish
 212         // IXUS220, SX220/230 - _MoveZoomLensWithPoint does not notify the JPEG engine of the new focal length,
 213         //                      causing incorrect lens distortion fixes to be applied; _PT_MoveOpticalZoomAt works
 214                 extern void _PT_MoveOpticalZoomAt(long*);
 215                 _PT_MoveOpticalZoomAt(&newpt);
 216   #else
 217             _MoveZoomLensWithPoint((short*)&newpt);
 218   #endif
 219 
 220                 // have to sleep here, zoom_busy set in another task, without sleep this will hang
 221                 while (zoom_busy) msleep(10);
 222 
 223                 // g10,g12 & sx30 only use this value for optical zoom
 224                 zoom_status=ZOOM_OPTICAL_MAX;
 225 
 226   #if !defined(CAM_USE_ALT_PT_MoveOpticalZoomAt) 
 227             _SetPropertyCase(PROPCASE_OPTICAL_ZOOM_POSITION, &newpt, sizeof(newpt));
 228   #endif
 229         }
 230 #else   // !(CAM_USE_ALT_SET_ZOOM_POINT)
 231     _MoveZoomLensWithPoint((short*)&newpt);
 232 
 233     // tight loop here hangs some cameras (the task that clears zoom_busy
 234     // is starved; seen at least on S95 and IXUS 220), so stick in a sleep
 235     while (zoom_busy) msleep(10);
 236 
 237     if (newpt==0) zoom_status=ZOOM_OPTICAL_MIN;
 238     else if (newpt >= zoom_points) zoom_status=ZOOM_OPTICAL_MAX;
 239     else zoom_status=ZOOM_OPTICAL_MEDIUM;
 240     _SetPropertyCase(PROPCASE_OPTICAL_ZOOM_POSITION, &newpt, sizeof(newpt));
 241 #endif  // !(CAM_USE_ALT_SET_ZOOM_POINT)
 242 }
 243 
 244 void lens_set_zoom_speed(long newspd)
 245 {
 246     if (newspd < 5) {
 247         newspd = 5;
 248     } else if (newspd > 100) {
 249         newspd = 100;
 250     }
 251     _SetZoomActuatorSpeedPercent((short*)&newspd);
 252 }
 253 
 254 void lens_set_focus_pos(long newpos)
 255 {
 256     if (newpos >= CAMERA_MAX_DIST) newpos = INFINITY_DIST; // Set to infinity value that will work on all cameras
 257     _MoveFocusLensToDistance((short*)&newpos);
 258     while ((shooting_is_flash_ready()!=1) || (focus_busy)) msleep(10);
 259     newpos = _GetFocusLensSubjectDistance();
 260     _SetPropertyCase(PROPCASE_SUBJECT_DIST1, &newpos, sizeof(newpos));
 261     _SetPropertyCase(PROPCASE_SUBJECT_DIST2, &newpos, sizeof(newpos));
 262 }
 263 
 264 void play_sound(unsigned sound)
 265 {
 266         static const int sounds[]={ 0x2001, //startup sound
 267                                 0x2002, //shutter sound
 268                                 0x2003, //button press sound
 269                                 0x2004, //self-timer sound
 270                                 0xC211, //short beep
 271                                 50000,  // AF confirmation
 272                                 0xC507, // error beep imo
 273                                 0x400D, // LONG ERROR BEEP CONTINIUOUS- warning, cannot be stopped (yet)
 274                             };
 275     if(sound >= sizeof(sounds)/sizeof(sounds[0]))
 276         return;
 277 
 278     _PT_PlaySound(sounds[sound], 0);
 279 }
 280 
 281 long stat_get_vbatt()
 282 {
 283     return _VbattGet();
 284 }
 285 
 286 //========================================================================
 287 // NOTE : some early DryOS cameras need a pointer rather than a value and the 
 288 //        xus30 & 40 want a char * string here. Override this funcion in camera's
 289 //        lib.c file if impelementing remote via battery 3rd terminal functionality.
 290 //        see http://chdk.setepontos.com/index.php?topic=10385.msg109353#msg109353
 291 //
 292 int __attribute__((weak)) GetAdChValue(int channel)        
 293 {
 294 #ifdef CAM_DRYOS
 295     return _GetAdChValue(channel);
 296 #else
 297     return _GetAdChValue(&channel);
 298 #endif
 299 }
 300 
 301 int get_battery_temp()
 302 {
 303     return _GetBatteryTemperature();
 304 }
 305 
 306 int get_ccd_temp()
 307 {
 308     return _GetCCDTemperature();
 309 }
 310 
 311 int get_optical_temp()
 312 {
 313     return _GetOpticalTemperature();
 314 }
 315 
 316 long get_tick_count()
 317 {
 318 long t;
 319 #if !CAM_DRYOS
 320     _GetSystemTime(&t);
 321     return t;
 322 #else
 323     return (int)_GetSystemTime(&t);
 324 #endif
 325 }
 326 
 327 #if CAM_HAS_ND_FILTER
 328 void PutInNdFilter()                { _PutInNdFilter(); }
 329 void PutOutNdFilter()               { _PutOutNdFilter(); }
 330 #endif
 331 
 332 short shooting_get_nd_value_ev96(void)
 333 {
 334 #if CAM_HAS_ND_FILTER
 335     return _get_nd_value();
 336 #else
 337     return 0;
 338 #endif
 339 }
 340 
 341 short shooting_get_nd_current_ev96(void)
 342 {
 343 #if CAM_HAS_ND_FILTER
 344     return _get_current_nd_value();
 345 #else
 346     return 0;
 347 #endif
 348 }
 349 
 350 long shooting_get_current_tv96()
 351 {
 352     // old cameras crash if _GetCurrentShutterSpeed called when inactive
 353     if(!shooting_get_imager_active()) {
 354         return SHOOTING_TV96_INVALID;
 355     }
 356     return _GetCurrentShutterSpeed();
 357 }
 358 long shooting_get_current_av96()    { return _GetCurrentAvValue(); }
 359 
 360 long IsStrobeChargeCompleted()      { return _IsStrobeChargeCompleted(); }
 361 void SetCurrentCaptureModeType()    { _SetCurrentCaptureModeType(); }
 362 
 363 #if CAM_HAS_IRIS_DIAPHRAGM
 364 // returns available Av range in AV96 on cameras with iris.
 365 // Function exists on a few later cameras without iris, behavior unknown.
 366 // Appears to be the full range, including smaller (higher F/ number) than available in Canon UI.
 367 // Note Min = smallest physical aperture = largest Av96 value
 368 short GetUsableMinAv(void) { return _GetUsableMinAv(); }
 369 short GetUsableMaxAv(void) { return _GetUsableMaxAv(); }
 370 #endif
 371 
 372 #if CAM_CAN_UNLOCK_OPTICAL_ZOOM_IN_VIDEO
 373 void UnsetZoomForMovie()            { _UnsetZoomForMovie(); }
 374 #endif
 375 
 376 #ifdef CAM_AV_OVERRIDE_IRIS_FIX
 377 int MoveIrisWithAv(short *v)        { return _MoveIrisWithAv(v); }
 378 #endif
 379 
 380 #if CAM_EV_IN_VIDEO
 381 void ExpCtrlTool_StartContiAE(int v1, int v2)   { _ExpCtrlTool_StartContiAE(v1,v2); }
 382 void ExpCtrlTool_StopContiAE(int v1, int v2)    { _ExpCtrlTool_StopContiAE(v1, v2); }
 383 short SetAE_ShutterSpeed(short *tv)             { return _SetAE_ShutterSpeed(tv); }
 384 #endif
 385 
 386 //----------------------------------------------------------------------------
 387 // I/O wrappers
 388 
 389 /*int creat (const char *name, int flags)
 390 {
 391     return _creat(name, flags);
 392 }*/
 393 
 394 extern int fileio_semaphore;
 395 
 396 int takeFileIOSemaphore()
 397 {
 398     int timeout = CAM_FILEIO_SEM_TIMEOUT;
 399 #if defined(CAM_IS_VID_REC_WORKS)
 400     if (is_video_recording())
 401         timeout = CAM_FILEIO_SEM_TIMEOUT_VID;
 402 #endif
 403 #if defined(OPT_FILEIO_STATS)
 404     int t = get_tick_count();
 405 #endif
 406     // Check fileio semaphore with timeout, if not available we are probably recording video
 407     if (_TakeSemaphore(fileio_semaphore,timeout) & 1)
 408     {
 409 #if defined(OPT_FILEIO_STATS)
 410         camera_info.fileio_stats.fileio_semaphore_errors++;
 411 #endif
 412         return 0;
 413     }
 414 #if defined(OPT_FILEIO_STATS)
 415     t = get_tick_count() - t;
 416     if (t > camera_info.fileio_stats.max_semaphore_timeout)
 417         camera_info.fileio_stats.max_semaphore_timeout = t;
 418 #endif
 419     return 1;
 420 }
 421 
 422 int open (const char *name, int flags, int mode )
 423 {
 424 #if defined(OPT_FILEIO_STATS)
 425     camera_info.fileio_stats.open_count++;
 426 #endif
 427 #if !CAM_DRYOS
 428     // Adjust O_TRUNC and O_CREAT flags for VxWorks
 429     // Remove O_APPEND flag if present (not in VxWorks)
 430     flags = (flags & ~(O_TRUNC|O_CREAT|O_APPEND)) | ((flags & (O_TRUNC|O_CREAT)) << 1);
 431 #else
 432     if(!name || name[0]!='A')
 433         return -1;
 434 #endif
 435     int haveSemaphore = takeFileIOSemaphore();
 436     if (!haveSemaphore)
 437 #if defined(CAM_IS_VID_REC_WORKS)
 438         if (!conf.allow_unsafe_io)
 439 #endif
 440             return -1;
 441     int fd = _Open(name, flags, mode);
 442     if (haveSemaphore)
 443         _GiveSemaphore(fileio_semaphore);
 444 #if defined(OPT_FILEIO_STATS)
 445     if (fd == -1)
 446         camera_info.fileio_stats.open_fail_count++;
 447 #endif
 448     return fd;
 449 }
 450 
 451 int close (int fd)
 452 {
 453 #if defined(OPT_FILEIO_STATS)
 454     camera_info.fileio_stats.close_count++;
 455 #endif
 456     if (fd == -1)
 457     {
 458 #if defined(OPT_FILEIO_STATS)
 459         camera_info.fileio_stats.close_badfile_count++;
 460 #endif
 461         return -1;
 462     }
 463     int haveSemaphore = takeFileIOSemaphore();
 464     if (!haveSemaphore)
 465 #if defined(CAM_IS_VID_REC_WORKS)
 466         if (!conf.allow_unsafe_io)
 467 #endif
 468             return -1;
 469     int r = _Close(fd);
 470     if (haveSemaphore)
 471         _GiveSemaphore(fileio_semaphore);
 472 #if defined(OPT_FILEIO_STATS)
 473     if (r == -1)
 474         camera_info.fileio_stats.close_fail_count++;
 475 #endif
 476     return r;
 477 }
 478 
 479 int write (int fd, const void *buffer, long nbytes)
 480 {
 481     if (fd == -1)
 482     {
 483 #if defined(OPT_FILEIO_STATS)
 484         camera_info.fileio_stats.write_badfile_count++;
 485 #endif
 486         return -1;
 487     }
 488     int haveSemaphore = takeFileIOSemaphore();
 489     if (!haveSemaphore)
 490 #if defined(CAM_IS_VID_REC_WORKS)
 491         if (!conf.allow_unsafe_io)
 492 #endif
 493             return -1;
 494     int r = _Write(fd, buffer, nbytes);
 495     if (haveSemaphore)
 496         _GiveSemaphore(fileio_semaphore);
 497     return r;
 498 }
 499 
 500 int read (int fd, void *buffer, long nbytes)
 501 {
 502     return _Read(fd, buffer, nbytes);
 503 }
 504 
 505 int lseek (int fd, long offset, int whence)
 506 {
 507     return _lseek(fd, offset, whence); /* yes, it's lower-case lseek here since Lseek calls just lseek (A610) */
 508 }
 509 
 510 long mkdir(const char *dirname)
 511 {
 512 #ifdef MKDIR_RETURN_ONE_ON_SUCCESS
 513     // mkdir returns 1 on success, 0 on fail. So, values are inverted, to be compatible with previous versions
 514     if(_MakeDirectory_Fut(dirname,1)) return 0;
 515     else                              return 1;
 516 #else
 517     return _MakeDirectory_Fut(dirname,-1); // meaning of second arg is not clear, firmware seems to use -1
 518 #endif
 519 }
 520 
 521 long mkdir_if_not_exist(const char *dirname)
 522 {
 523     // Check if directory exists and create it if it does not.
 524     if (stat(dirname,0) != 0) return mkdir(dirname);
 525     return 0;   // Success
 526 }
 527 
 528 int remove(const char *name)
 529 {
 530 #ifdef CAM_DRYOS_2_3_R39
 531     // For DryOS R39 and later need to check if 'name' is a file or directory
 532     // and call appropriate delete function.
 533     struct stat st;
 534     if (stat(name,&st) == 0)
 535     {
 536         if (st.st_attrib & DOS_ATTR_DIRECTORY)
 537                 return _DeleteDirectory_Fut(name);
 538         else
 539                 return _DeleteFile_Fut(name);
 540     }
 541     return -1;  // return fail - file / directory does not exist
 542 #else
 543     return _DeleteFile_Fut(name);
 544 #endif
 545 }
 546 
 547 //----------------------------------------------------------------------------
 548 // minimal directory wrappers, rest of implementation is in core/lib_thumb.c
 549 
 550 int fw_closedir(void *d)
 551 {
 552     int have_semaphore = takeFileIOSemaphore();
 553     if (!have_semaphore)
 554 #if defined(CAM_IS_VID_REC_WORKS)
 555         if (!conf.allow_unsafe_io)
 556 #endif
 557             return -1;
 558 
 559     extern int _closedir(void *d);
 560     int ret = _closedir(d);
 561 
 562     if (have_semaphore)
 563         _GiveSemaphore(fileio_semaphore);
 564 
 565     return ret;
 566 }
 567 
 568 #if defined(CAM_DRYOS)
 569     int get_fstype(void)
 570     {
 571 #ifdef CAM_DRYOS_2_3_R39
 572         // fw function returns 1..3 for FAT 12-16-32, 4 for exFAT
 573         // TODO: fix this if any supported camera gets more than 1 drive OR the returned values change
 574         extern int _get_fstype(int);
 575         return _get_fstype(0);
 576 #else
 577         return 0;
 578 #endif
 579     }
 580 
 581     void *fw_opendir(const char* name)
 582     {
 583         void *ret;
 584         int have_semaphore = takeFileIOSemaphore();
 585         if (!have_semaphore)
 586 #if defined(CAM_IS_VID_REC_WORKS)
 587             if (!conf.allow_unsafe_io)
 588 #endif
 589                 return NULL;
 590 
 591         extern void *_OpenFastDir(const char* name);
 592         ret = _OpenFastDir(name);
 593 
 594         if (have_semaphore)
 595             _GiveSemaphore(fileio_semaphore);
 596 
 597         return ret;
 598     }
 599 
 600     int fw_readdir(void *d, void* dd)
 601     {
 602         extern int _ReadFastDir(void *d, void* dd);
 603         return _ReadFastDir(d, dd);
 604     }
 605 
 606 #else // Vx
 607 
 608     void *fw_opendir(const char* name)
 609     {
 610         void *ret;
 611         int have_semaphore = takeFileIOSemaphore();
 612         if (!have_semaphore)
 613 #if defined(CAM_IS_VID_REC_WORKS)
 614             if (!conf.allow_unsafe_io)
 615 #endif
 616                 return NULL;
 617 
 618         extern void *_opendir(const char* name);
 619         ret = _opendir(name);
 620 
 621         if (have_semaphore)
 622             _GiveSemaphore(fileio_semaphore);
 623 
 624         return ret;
 625     }
 626 
 627     void *fw_readdir(void *d)
 628     {
 629         extern void *_readdir(void *d);
 630         return _readdir(d);
 631     }
 632 
 633 #endif // CAM_DRYOS
 634 
 635 //-----------------------------------------------------------------------------------
 636 
 637 // Internal camera firmare 'stat' structures
 638 
 639 #if !CAM_DRYOS
 640 
 641 struct  __stat  // VxWorks
 642 {
 643     unsigned long       st_dev;         /* device ID number */
 644     unsigned long       st_ino;         /* file serial number */
 645     unsigned short      st_mode;        /* file mode (see below) */
 646     short               st_nlink;       /* number of links to file */
 647     short               st_uid;         /* user ID of file's owner */
 648     short               st_gid;         /* group ID of file's group */
 649     unsigned long       st_rdev;        /* device ID, only if special file */
 650     unsigned long       st_size;        /* size of file, in bytes */
 651     unsigned long       st_atime;       /* time of last access */
 652     unsigned long       st_mtime;       /* time of last modification */
 653     unsigned long       st_ctime;       /* time of last change of file status */
 654     long                st_blksize;
 655     long                st_blocks;
 656     unsigned char       st_attrib;      /* file attribute byte (dosFs only) */
 657     int                 reserved1;      /* reserved for future use */
 658     int                 reserved2;      /* reserved for future use */
 659     int                 reserved3;      /* reserved for future use */
 660     int                 reserved4;      /* reserved for future use */
 661     int                 reserved5;      /* reserved for future use */
 662     int                 reserved6;      /* reserved for future use */
 663 };
 664 
 665 #else
 666 
 667 #ifndef CAM_DRYOS_2_3_R39
 668 
 669 struct  __stat  // DryOS pre R39
 670     {
 671     unsigned long       st_dev;         //?
 672     unsigned long       st_ino;         //?
 673     unsigned short      st_mode;        //?
 674     short               st_nlink;       //?
 675     short               st_uid;         //?
 676     short               st_gid;         //?
 677     unsigned long       st_atime;       //?
 678     unsigned long       st_mtime;       //?
 679     unsigned long       st_ctime;       //?
 680     unsigned long       st_size;
 681     long                st_blksize;     //?
 682     long                st_blocks;      //?
 683     unsigned char       st_attrib;
 684     int                 reserved1;      //
 685     int                 reserved2;      //
 686     int                 reserved3;      //
 687     int                 reserved4;      //
 688     int                 reserved5;      //
 689     int                 reserved6;      //
 690 };
 691 
 692 #else
 693 
 694 struct __stat   // DryOS post R39
 695 {
 696     unsigned long       st_unknown_1;
 697     unsigned long       st_attrib;
 698     unsigned long       st_size;
 699     unsigned long       st_ctime;
 700     unsigned long       st_mtime;
 701     unsigned long       st_unknown_2;
 702 };
 703 
 704 #endif//CAM_DRYOS_2_3_R39
 705 
 706 #endif//CAM_DRYOS
 707 
 708 int stat(const char *name, struct stat *pStat)
 709 {
 710     // sanity check. canon firmware hangup if start not from 'A/'
 711     if ( !name || (name[0] | 0x20)!='a' || name[1]!='/' ) return 1;
 712 
 713     // use temp __stat stucture to match camera firmware
 714     // and copy values across to output
 715     struct __stat lStat;
 716     int rv = _stat(name, &lStat);
 717     if (pStat)
 718     {
 719         if (rv == 0)
 720         {
 721             pStat->st_attrib = lStat.st_attrib;
 722             pStat->st_size = lStat.st_size;
 723             pStat->st_ctime = lStat.st_ctime;
 724             pStat->st_mtime = lStat.st_mtime;
 725         }
 726         else
 727         {
 728             memset( pStat, 0, sizeof(struct stat));
 729         }
 730     }
 731     return rv;
 732 }
 733 
 734 FILE *fopen(const char *filename, const char *mode) {
 735 #ifdef CAM_DRYOS
 736     if(!filename || filename[0]!='A') {
 737         return NULL;
 738     }
 739 #endif
 740 
 741     // Check fileio semaphore, if not available we are probably recording video
 742     if (!takeFileIOSemaphore())
 743         return NULL;
 744     _GiveSemaphore(fileio_semaphore);
 745 
 746     return (FILE *)_Fopen_Fut(filename,mode);
 747 }
 748 
 749 long fclose(FILE *f) {
 750     return _Fclose_Fut((long)f);
 751 }
 752 
 753 long fread(void *buf, long elsize, long count, FILE *f) {
 754     return _Fread_Fut(buf,elsize,count,(long)f);
 755 }
 756 
 757 long fwrite(const void *buf, long elsize, long count, FILE *f) {
 758     return _Fwrite_Fut(buf,elsize,count,(long)f);
 759 }
 760 
 761 long fseek(FILE *file, long offset, long whence) {
 762     return _Fseek_Fut((long)file,offset,whence);
 763 }
 764 
 765 long feof(FILE * file) {
 766     return _Feof_Fut((long)file);
 767 }
 768 
 769 long fflush(FILE * file) {
 770     return _Fflush_Fut((long)file);
 771 }
 772 
 773 char *fgets(char *buf, int n, FILE *f) {
 774     return _Fgets_Fut(buf,n,(int)f);
 775 }
 776 
 777 int rename(const char *oldname, const char *newname) {
 778  return _RenameFile_Fut(oldname, newname);
 779 }
 780 
 781 unsigned int GetFreeCardSpaceKb(void){
 782         return (_GetDrive_FreeClusters(0)*(_GetDrive_ClusterSize(0)>>9))>>1;
 783 }
 784 
 785 unsigned int GetTotalCardSpaceKb(void){
 786         return (_GetDrive_TotalClusters(0)*(_GetDrive_ClusterSize(0)>>9))>>1;
 787 }
 788 
 789 //----------------------------------------------------------------------------
 790 
 791 int errnoOfTaskGet(int tid) {
 792 #if !CAM_DRYOS
 793     return _errnoOfTaskGet(tid);
 794 #else
 795     return 0;
 796 #endif
 797 }
 798 
 799 //----------------------------------------------------------------------------
 800 // String wrappers
 801 
 802 long strlen(const char *s) {
 803     return _strlen(s);
 804 }
 805 
 806 int strcmp(const char *s1, const char *s2) {
 807     return _strcmp(s1, s2);
 808 }
 809 
 810 int strncmp(const char *s1, const char *s2, long n) {
 811     return _strncmp(s1, s2, n);
 812 }
 813 
 814 char *strchr(const char *s, int c) {
 815     return _strchr(s, c);
 816 }
 817 
 818 char *strcpy(char *dest, const char *src) {
 819     return _strcpy(dest, src);
 820 }
 821 
 822 char *strncpy(char *dest, const char *src, long n) {
 823     return _strncpy(dest, src, n);
 824 }
 825 
 826 char *strcat(char *dest, const char *app) {
 827     return _strcat(dest, app);
 828 }
 829 
 830 char *strrchr(const char *s, int c) {
 831     return _strrchr(s, c);
 832 }
 833 
 834 long strtol(const char *nptr, char **endptr, int base) {
 835     return _strtol(nptr, endptr, base);
 836 }
 837 
 838 unsigned long strtoul(const char *nptr, char **endptr, int base) {
 839 #if CAM_DRYOS
 840     return (unsigned long)_strtolx(nptr, endptr, base, 0);
 841 #else
 842     return _strtoul(nptr, endptr, base);
 843 #endif
 844 }
 845 
 846 #if !CAM_DRYOS
 847 char *strpbrk(const char *s, const char *accept)
 848 {
 849     return _strpbrk(s, accept);
 850 }
 851 #endif
 852 
 853 //----------------------------------------------------------------------------
 854 
 855 long sprintf(char *s, const char *st, ...)
 856 {
 857     long res;
 858     __builtin_va_list va;
 859     __builtin_va_start(va, st);
 860     res = _vsprintf(s, st, va);
 861     __builtin_va_end(va);
 862     return res;
 863 }
 864 
 865 // strerror exists on vxworks cams,
 866 // but it does about the same thing as this
 867 const char *strerror(int en) {
 868 #if !CAM_DRYOS
 869     static char msg[20];
 870     sprintf(msg,"errno 0x%X",en);
 871     return msg;
 872 #else
 873     return "error";
 874 #endif
 875 }
 876 
 877 //----------------------------------------------------------------------------
 878 // Time wrappers
 879 
 880 unsigned long time(unsigned long *timer) {
 881     return _time(timer);
 882 }
 883 
 884 int utime(const char *file, struct utimbuf *newTimes) {
 885 #if !CAM_DRYOS
 886     return _utime(file, newTimes);
 887 #else
 888     int res=0;
 889     int fd;
 890     fd = _open(file, 0, 0);
 891 
 892 #ifdef CAM_DRYOS_2_3_R39
 893     if (fd>=0) {
 894         _close(fd);
 895         res=_SetFileTimeStamp(file, newTimes->modtime, newTimes->actime);
 896     }
 897 #else
 898     if (fd>=0) {
 899         res=_SetFileTimeStamp(fd, newTimes->modtime, newTimes->actime);
 900         _close(fd);
 901     }
 902     // return value compatibe with utime: ok=0 fail=-1
 903 #endif
 904     return (res)?0:-1;
 905 #endif
 906 }
 907 
 908 struct tm *localtime(const time_t *_tod) {
 909 #if !CAM_DRYOS
 910     return _localtime(_tod);
 911 #else
 912     // for DRYOS cameras do something with this!  - sizeof(x[]) must be >= sizeof(struct tm) :  'static int x[9];'
 913     static int x[10];
 914     return _LocalTime(_tod, &x);
 915 #endif
 916 }
 917 
 918 long strftime(char *s, unsigned long maxsize, const char *format, const struct tm *timp) {
 919         return _strftime(s,maxsize,format,timp);
 920 }
 921 
 922 time_t mktime(struct tm *timp) {
 923 #if !CAM_DRYOS
 924         return _mktime(timp);
 925 #else
 926         int timp_ext[10]; // struct tm + a ptr
 927         _memcpy(timp_ext,timp,9*sizeof(int));
 928         timp_ext[9]=0;
 929         long retval = _mktime_ext(&timp_ext);
 930         _memcpy(timp,timp_ext,9*sizeof(int));
 931         return retval;
 932 #endif
 933 }
 934 
 935 //----------------------------------------------------------------------------
 936 // Math wrappers
 937 
 938 double _log(double x) {
 939     return __log(x);
 940 }
 941 
 942 double _log10(double x) {
 943     return __log10(x);
 944 }
 945 
 946 double _pow(double x, double y) {
 947     return __pow(x, y);
 948 }
 949 
 950 double _sqrt(double x) {
 951     return __sqrt(x);
 952 }
 953 
 954 //----------------------------------------------------------------------------
 955 
 956 #ifdef OPT_EXMEM_MALLOC
 957 void *exmem_alloc(int pool_id,int size,int unk,int unk2)
 958 {
 959     return _exmem_alloc(pool_id,size,unk,unk2);
 960 }
 961 #endif
 962 
 963 void *canon_malloc(long size)
 964 {
 965     return _malloc(size);
 966 }
 967 
 968 void canon_free(void *p)
 969 {
 970     _free(p);
 971 }
 972 
 973 void *umalloc(long size) {
 974     return _AllocateUncacheableMemory(size);
 975 }
 976 
 977 void ufree(void *p) {
 978     return _FreeUncacheableMemory(p);
 979 }
 980 
 981 void *memcpy(void *dest, const void *src, long n) {
 982     return _memcpy(dest, src, n);
 983 }
 984 
 985 void *memset(void *s, int c, int n) {
 986     return _memset(s, c, n);
 987 }
 988 
 989 int memcmp(const void *s1, const void *s2, long n) {
 990     return _memcmp(s1, s2, n);
 991 }
 992 
 993 #if !CAM_DRYOS
 994 void *memchr(const void *s, int c, int n) {
 995         return _memchr(s,c,n);
 996 }
 997 #endif
 998 
 999 //----------------------------------------------------------------------------
1000 
1001 void GetMemInfo(cam_meminfo *camera_meminfo)
1002 {
1003 // Use firmware GetMemInfo function to retrieve info about Canon heap memory allocation
1004 
1005 #if defined(CAM_DRYOS)
1006     // Prior to dryos R39 GetMemInfo returns 9 values, after R39 it returns 10 (all but 1 are used in each case)
1007     int fw_info[10];
1008     extern void _GetMemInfo(int*);
1009     _GetMemInfo(fw_info);
1010 
1011 #if defined(CAM_DRYOS_2_3_R39)
1012     // For newer dryos version copy all 9 used values to CHDK structure
1013     camera_meminfo->start_address        = fw_info[0];
1014     camera_meminfo->end_address          = fw_info[1];
1015     camera_meminfo->total_size           = fw_info[2];
1016     camera_meminfo->allocated_size       = fw_info[3];
1017     camera_meminfo->allocated_peak       = fw_info[4];
1018     camera_meminfo->allocated_count      = fw_info[5];
1019     camera_meminfo->free_size            = fw_info[6];
1020     camera_meminfo->free_block_max_size  = fw_info[7];
1021     camera_meminfo->free_block_count     = fw_info[8];
1022 #else
1023     // For older dryos version copy 8 used values to CHDK structure and calculate missing value
1024     camera_meminfo->start_address        = fw_info[0];
1025     camera_meminfo->end_address          = fw_info[0] + fw_info[1];
1026     camera_meminfo->total_size           = fw_info[1];
1027     camera_meminfo->allocated_size       = fw_info[2];
1028     camera_meminfo->allocated_peak       = fw_info[3];
1029     camera_meminfo->allocated_count      = fw_info[4];
1030     camera_meminfo->free_size            = fw_info[5];
1031     camera_meminfo->free_block_max_size  = fw_info[6];
1032     camera_meminfo->free_block_count     = fw_info[7];
1033 #endif
1034 #else // vxworks
1035 extern int sys_mempart_id;
1036     int fw_info[5];
1037     // -1 for invalid
1038     memset(camera_meminfo,0xFF,sizeof(cam_meminfo));
1039 #ifdef CAM_NO_MEMPARTINFO
1040     camera_meminfo->free_block_max_size = _memPartFindMax(sys_mempart_id);
1041 #else
1042     _memPartInfoGet(sys_mempart_id,fw_info);
1043     // TODO we could fill in start address from _start + MEMISOSIZE, if chdk not in exmem
1044     // these are guessed, look reasonable on a540
1045     camera_meminfo->free_size = fw_info[0];
1046     camera_meminfo->free_block_count = fw_info[1];
1047     camera_meminfo->free_block_max_size = fw_info[2];
1048     camera_meminfo->allocated_size = fw_info[3];
1049     camera_meminfo->allocated_count = fw_info[4];
1050 #endif
1051 #endif
1052 }
1053 
1054 //----------------------------------------------------------------------------
1055 
1056 int rand(void) {
1057     return _rand();
1058 }
1059 
1060 void *srand(unsigned int seed) {
1061     return _srand(seed);
1062 }
1063 
1064 void qsort(void *__base, int __nelem, int __size, int (*__cmp)(const void *__e1, const void *__e2)) {
1065     _qsort(__base, __nelem, __size, __cmp);
1066 }
1067 
1068 static int shutdown_disabled = 0;
1069 void disable_shutdown() {
1070     if (!shutdown_disabled) {
1071         _LockMainPower();
1072         shutdown_disabled = 1;
1073     }
1074 }
1075 
1076 void enable_shutdown() {
1077     if (shutdown_disabled) {
1078         _UnlockMainPower();
1079         shutdown_disabled = 0;
1080     }
1081 }
1082 
1083 void camera_shutdown_in_a_second(void) {
1084     int i;
1085     _SetAutoShutdownTime(1); // 1 sec
1086     for (i=0;i<200;i++)
1087         _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").
1088 }
1089 
1090 void EnterToCompensationEVF(void)
1091 {
1092   _EnterToCompensationEVF();
1093 }
1094 
1095 void ExitFromCompensationEVF()
1096 {
1097   _ExitFromCompensationEVF();
1098 }
1099 
1100 void TurnOnBackLight(void)
1101 {
1102   _TurnOnBackLight();
1103 }
1104 
1105 void TurnOffBackLight(void)
1106 {
1107   _TurnOffBackLight();
1108 }
1109 
1110 extern void gui_set_need_restore();
1111 
1112 void TurnOnDisplay(void)
1113 {
1114   _TurnOnDisplay();
1115   // required to re-draw the canon and CHDK UI after re-enabling display
1116   gui_set_need_restore() ;
1117 }
1118 
1119 void TurnOffDisplay(void)
1120 {
1121   _TurnOffDisplay();
1122 }
1123 
1124 void DoAELock(void)
1125 {
1126   if (!camera_info.state.mode_play)
1127   {
1128      _DoAELock();
1129   }
1130 }
1131 
1132 void UnlockAE(void)
1133 {
1134   if (!camera_info.state.mode_play)
1135   {
1136      _UnlockAE();
1137   }
1138 }
1139 
1140 void DoAFLock(void)
1141 {
1142   if (!camera_info.state.mode_play)
1143   {
1144      int af_lock=1;
1145      _DoAFLock();
1146      set_property_case(PROPCASE_AF_LOCK,&af_lock,sizeof(af_lock));
1147   }
1148 }
1149 
1150 void UnlockAF(void)
1151 {
1152   if (!camera_info.state.mode_play)
1153   {
1154      int af_lock=0;
1155      _UnlockAF();
1156      set_property_case(PROPCASE_AF_LOCK,&af_lock,sizeof(af_lock));
1157   }
1158 }
1159 
1160 int EngDrvRead(int gpio_reg)
1161 {
1162   return _EngDrvRead(gpio_reg);
1163 }
1164 
1165 #if CAM_MULTIPART
1166 
1167 #define SECTOR_SIZE 512
1168 static char *mbr_buf=(void*)0;
1169 static unsigned long drive_sectors;
1170 
1171 int is_mbr_loaded()
1172 {
1173         return (mbr_buf == (void*)0) ? 0 : 1;
1174 }
1175 
1176 #ifndef CAM_DRYOS
1177 
1178 int mbr_read(char* mbr_sector, unsigned long drive_total_sectors, unsigned long *part_start_sector,  unsigned long *part_length){
1179 // return value: 1 - success, 0 - fail
1180 // called only in VxWorks
1181 
1182  int offset=0x10; // points to partition #2
1183  int valid;
1184 
1185  if ((mbr_sector[0x1FE]!=0x55) || (mbr_sector[0x1FF]!=0xAA)) return 0; // signature check
1186 
1187  mbr_buf=_AllocateUncacheableMemory(SECTOR_SIZE);
1188  _memcpy(mbr_buf,mbr_sector,SECTOR_SIZE);
1189  drive_sectors=drive_total_sectors;
1190 
1191  while(offset>=0) {
1192 
1193   *part_start_sector=(*(unsigned short*)(mbr_sector+offset+0x1C8)<<16) | *(unsigned short*)(mbr_sector+offset+0x1C6);
1194   *part_length=(*(unsigned short*)(mbr_sector+offset+0x1CC)<<16) | *(unsigned short*)(mbr_sector+offset+0x1CA);
1195 
1196   valid= (*part_start_sector) && (*part_length) &&
1197          (*part_start_sector<=drive_total_sectors) &&
1198          (*part_start_sector+*part_length<=drive_total_sectors) &&
1199          ((mbr_sector[offset+0x1BE]==0) || (mbr_sector[offset+0x1BE]==0x80)); // status: 0x80 (active) or 0 (non-active)
1200 
1201   if (valid && ((mbr_sector[0x1C2+offset]==0x0B) || (mbr_sector[0x1C2+offset]==0x0C))) break;   // FAT32 secondary partition
1202 
1203   offset-=0x10;
1204 
1205  }
1206 
1207  return valid;
1208 }
1209 
1210 #else
1211 
1212 int mbr_read_dryos(unsigned long drive_total_sectors, char* mbr_sector ){
1213 // Called only in DRYOS
1214  mbr_buf=_AllocateUncacheableMemory(SECTOR_SIZE);
1215  _memcpy(mbr_buf,mbr_sector,SECTOR_SIZE);
1216  drive_sectors=drive_total_sectors;
1217  return drive_total_sectors;
1218 }
1219 
1220 #endif
1221 
1222 int get_part_count(void)
1223 {
1224   unsigned long part_start_sector, part_length;
1225   char part_status, part_type;
1226   int i;
1227   int count=0;
1228   if (is_mbr_loaded())
1229   {
1230     for (i=0; i<=3;i++)
1231     {
1232       part_start_sector=(*(unsigned short*)(mbr_buf+i*16+0x1C8)<<16) | *(unsigned short*)(mbr_buf+i*16+0x1C6);
1233       part_length=(*(unsigned short*)(mbr_buf+i*16+0x1CC)<<16) | *(unsigned short*)(mbr_buf+i*16+0x1CA);
1234       part_status=mbr_buf[i*16+0x1BE];
1235       part_type=mbr_buf[0x1C2+i*16];
1236       if ( part_start_sector && part_length && part_type && ((part_status==0) || (part_status==0x80)) ) count++;
1237     }
1238   }
1239   return count;
1240 }
1241 int get_part_type()
1242 {
1243   int partType = 0x00;
1244   if (is_mbr_loaded())
1245   {
1246     partType=mbr_buf[0x1C2+(get_active_partition()-1)*16];
1247   }
1248   return partType;
1249 } 
1250 
1251 static int boot_partition = 0;
1252 static int partition_changed = 0;
1253 int is_partition_changed()
1254 {
1255   return partition_changed;
1256 }
1257 
1258 int swap_partitions(int new_partition)
1259 {
1260   if (is_mbr_loaded())
1261   {
1262     int i,j,p;
1263     char c;
1264     
1265     int partition_count = get_part_count();
1266     int active_partition = get_active_partition();
1267     
1268     if(!boot_partition)
1269     {
1270       boot_partition = active_partition;
1271     }
1272 
1273     // wrong input
1274     if( new_partition > partition_count || new_partition <= 0 )
1275     {
1276       return 0;
1277     }
1278     partition_changed = (new_partition==boot_partition)?0:1;
1279     
1280     // rotate partitions till new_partition is found
1281     for(j=0;j<partition_count;++j)
1282     {
1283       if(new_partition == get_active_partition())
1284       {
1285         break;
1286       }
1287       for(i=0;i<16;i++)
1288       {
1289         c=mbr_buf[i+0x1BE];
1290         for(p=1; p<partition_count; ++p)
1291         {
1292           mbr_buf[i+(p-1)*16+0x1BE]=mbr_buf[i+p*16+0x1BE];
1293         }
1294         mbr_buf[i+(partition_count-1)*16+0x1BE]=c;
1295       }
1296     }
1297     _WriteSDCard(0,0,1,mbr_buf);
1298   }
1299   return 1;
1300 }
1301 
1302 unsigned char get_active_partition(void)
1303 {
1304   unsigned int  partition_start[4];
1305   unsigned char partition_number = 1;
1306   int partition_count = get_part_count();
1307   int i;
1308 
1309   for( i=0; i<partition_count; ++i )
1310   {
1311     int a = mbr_buf[0x01C6+(i)*16];
1312     int b = mbr_buf[0x01C7+(i)*16];
1313     int c = mbr_buf[0x01C8+(i)*16];
1314     int d = mbr_buf[0x01C9+(i)*16];
1315     partition_start[i] = (((((d<<8) +c)<<8) +b)<<8) +a;
1316   }
1317   for( i=1; i<partition_count; ++i )
1318   {
1319     if(partition_start[i]<partition_start[0])
1320     {
1321       ++partition_number;
1322     }
1323   }
1324   return partition_number;
1325 }
1326 
1327 void create_partitions(void){
1328         if (is_mbr_loaded())
1329         {
1330          unsigned long start, length;
1331          char type;
1332 
1333          _memset(mbr_buf,0,SECTOR_SIZE);
1334 
1335          start=1; length=2*1024*1024/SECTOR_SIZE; //2 Mb
1336          type=1; // FAT primary
1337          mbr_buf[0x1BE + 4]=type;
1338          mbr_buf[0x1BE + 8]=start;   mbr_buf[0x1BE + 9]=start>>8;   mbr_buf[0x1BE + 10]=start>>16;  mbr_buf[0x1BE + 11]=start>>24;
1339          mbr_buf[0x1BE + 12]=length; mbr_buf[0x1BE + 13]=length>>8; mbr_buf[0x1BE + 14]=length>>16; mbr_buf[0x1BE + 15]=length>>24;
1340 
1341          start=start+length; length=drive_sectors-start-1;
1342          type=0x0B;  //FAT32 primary;
1343          mbr_buf[0x1CE + 4]=type;
1344          mbr_buf[0x1CE + 8]=start;   mbr_buf[0x1CE + 9]=start>>8;   mbr_buf[0x1CE + 10]=start>>16;  mbr_buf[0x1CE + 11]=start>>24;
1345          mbr_buf[0x1CE + 12]=length; mbr_buf[0x1CE + 13]=length>>8; mbr_buf[0x1CE + 14]=length>>16; mbr_buf[0x1CE + 15]=length>>24;
1346 
1347          mbr_buf[0x1FE]=0x55; mbr_buf[0x1FF]=0xAA; // signature;
1348 
1349          _WriteSDCard(0,0,1,mbr_buf);
1350         }
1351 }
1352 
1353 #else
1354 
1355 // Dummy for scripts if not implemented in camera
1356 int swap_partitions(int new_partition) { return 0; }
1357 int get_part_count(void) { return 1; }
1358 int get_part_type() { return 0; }
1359 unsigned char get_active_partition(void) { return 1; }
1360 int is_partition_changed() { return 0; }
1361 
1362 #endif
1363 
1364 int mute_on_zoom(int x){
1365  static int old_busy=0;
1366  int busy=zoom_busy||focus_busy;
1367  if (old_busy!=busy) {
1368   if (busy) {
1369 #if CAM_CAN_MUTE_MICROPHONE
1370    if (conf.mute_on_zoom) _TurnOffMic();
1371 #endif
1372    }
1373    else {
1374 #if CAM_CAN_MUTE_MICROPHONE
1375   if (conf.mute_on_zoom) _TurnOnMic();
1376 #endif
1377 #if CAM_EV_IN_VIDEO
1378   if (get_ev_video_avail()) set_ev_video_avail(0);
1379 #endif
1380   }
1381   old_busy=busy;
1382  }
1383  return x; // preserve R0 if called from assembler
1384 }
1385 
1386 
1387 #if CAM_AF_SCAN_DURING_VIDEO_RECORD
1388 void MakeAFScan(void){
1389  int a=0, save;
1390  if (zoom_busy || focus_busy) return;
1391  save=some_flag_for_af_scan;
1392  some_flag_for_af_scan=0;
1393 #if CAM_AF_SCAN_DURING_VIDEO_RECORD == 2
1394  parameter_for_af_scan=3;
1395 #endif
1396  _MakeAFScan(&a, 3);
1397  some_flag_for_af_scan=save;
1398 #if CAM_RESET_AEL_AFTER_VIDEO_AF
1399  int ae_lock;
1400  get_property_case(PROPCASE_AE_LOCK,&ae_lock,sizeof(ae_lock));
1401  if (ae_lock == 0)                                              // AE not locked so ensure it is unlocked after re-focus
1402          _ExpCtrlTool_StartContiAE(0,0);
1403  else                                                                   // AE locked before so re-lock after
1404          _ExpCtrlTool_StopContiAE(0,0);
1405 #else
1406  _ExpCtrlTool_StartContiAE(0,0);
1407 #endif
1408 }
1409 #endif
1410 
1411 long __attribute__((weak)) get_jogdial_direction(void)  { return 0; }
1412 void __attribute__((weak)) JogDial_CW(void)     {}
1413 void __attribute__((weak)) JogDial_CCW(void)    {}
1414 
1415 #if defined (DNG_EXT_FROM)
1416 
1417 #define DNG_EXT_TO ".DNG"
1418 
1419 typedef int(*p_some_f)(char*, int);
1420 
1421 extern p_some_f some_f_for_dng;  // camera variable!
1422 extern char* second_ext_for_dng; // camera variable!
1423 
1424 p_some_f default_some_f;
1425 char *   default_second_ext;
1426 
1427 int my_some_f(char *s, int x){
1428   char *f;
1429   f=strstr(s, DNG_EXT_FROM);
1430   if (f) _memcpy(f, DNG_EXT_TO, sizeof(DNG_EXT_TO)-1);
1431   return default_some_f(s, x);
1432 }
1433 
1434 void save_ext_for_dng(void){
1435  default_some_f=some_f_for_dng;
1436  default_second_ext=second_ext_for_dng;
1437 }
1438 
1439 void change_ext_to_dng(void){
1440  some_f_for_dng=my_some_f;
1441  second_ext_for_dng=DNG_EXT_TO;
1442 }
1443 
1444 void change_ext_to_default(void){
1445  some_f_for_dng=default_some_f;
1446  second_ext_for_dng=default_second_ext;
1447 }
1448 
1449 #endif
1450 
1451 #if !CAM_DRYOS
1452 static long drv_struct[16];
1453 #endif
1454 
1455 long dh_err()
1456 {
1457     return -1;
1458 }
1459 
1460 #if !CAM_DRYOS
1461 void drv_self_hide()
1462 {
1463     long drvnum;
1464 
1465     drvnum = _iosDrvInstall(dh_err,dh_err,dh_err,dh_err,dh_err,dh_err,dh_err);
1466     if (drvnum >= 0)
1467         _iosDevAdd(drv_struct, "A/DISKBOOT.BIN", drvnum);
1468 }
1469 
1470 void drv_self_unhide()
1471 {
1472  _iosDevDelete(drv_struct);
1473 }
1474 #endif
1475 
1476 int  apex2us(int apex_tv){
1477 #if CAM_EXT_TV_RANGE
1478 /*
1479  Extended Tv, by barberofcivil, http://chdk.setepontos.com/index.php/topic,4392.0.html
1480  Explanation by reyalP:
1481  In every port, the original shutter overrides (as opposed to super long exposure) worked by
1482  setting the propcase values at some point after auto-exposure has happened (except in manual
1483  modes, where the manual control propcases may be used instead). The Canon code previously took
1484  these values unchanged for short exposures. In newer cameras, like on the SX10 / SD980, the value
1485  is changed, apparently some time after it has been retrieved from the propcase. We know this is
1486  the case, because the propcase value itself doesn't get clamped to the allowed range (if it did,
1487  barberofcivil's code wouldn't work).
1488 */
1489         short tv;
1490         tv = shooting_get_tv96();
1491         if (tv<-576 || tv!=apex_tv) return 1000000.0*pow(2.0, -tv/96.0);
1492         else return _apex2us(apex_tv);
1493 #else
1494         return 0;
1495 #endif
1496 }
1497 
1498 void PostLogicalEventForNotPowerType(unsigned id, unsigned x) {
1499         _PostLogicalEventForNotPowerType(id,x);
1500 }
1501 
1502 void PostLogicalEventToUI(unsigned id, unsigned x) {
1503         _PostLogicalEventToUI(id,x);
1504 }
1505 
1506 void SetLogicalEventActive(unsigned id, unsigned state) {
1507         _SetLogicalEventActive(id, state);
1508 }
1509 
1510 void SetScriptMode(unsigned mode) {
1511         _SetScriptMode(mode);
1512 }
1513 
1514 // TODO this belongs lib.c, but not all cameras include it
1515 // same as bitmap width for most cameras, override in platform/sub/lib.c as needed
1516 int __attribute__((weak)) vid_get_viewport_width() {
1517         return camera_screen.width;
1518 }
1519 
1520 // Physical width of viewport row in bytes
1521 int __attribute__((weak)) vid_get_viewport_byte_width() {
1522         return 720 * 6 / 4;     // For most cameras viewport is 720 pixels wide, each group of 4 pixels uses 6 bytes (UYVYYY)
1523 }
1524 
1525 // Y multiplier for cameras with 480 pixel high viewports (CHDK code assumes 240)
1526 int __attribute__((weak)) vid_get_viewport_yscale() {
1527         return 1;               // For most cameras viewport is 240 pixels high
1528 }
1529 
1530 // viewport x offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay)
1531 int __attribute__((weak)) vid_get_viewport_xoffset() {
1532         return 0;
1533 }
1534 
1535 // viewport y offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay)
1536 int __attribute__((weak)) vid_get_viewport_yoffset() {
1537         return 0;
1538 }
1539 
1540 // viewport display x offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay)
1541 int __attribute__((weak)) vid_get_viewport_display_xoffset() {
1542         return vid_get_viewport_xoffset();
1543 }
1544 
1545 // viewport display y offset - used when image size != viewport size (zebra, histogram, motion detect & edge overlay)
1546 int __attribute__((weak)) vid_get_viewport_display_yoffset() {
1547         return vid_get_viewport_yoffset();
1548 }
1549 
1550 // format of live view viewport
1551 #ifndef THUMB_FW
1552 int vid_get_viewport_type() {
1553         return LV_FB_YUV8;
1554 }
1555 // D6 cameras must define
1556 #endif
1557 
1558 // for cameras with two (or more?) RAW buffers this can be used to speed up DNG creation by
1559 // calling reverse_bytes_order only once. Override in platform/sub/lib.c
1560 char __attribute__((weak)) *hook_alt_raw_image_addr() {
1561         return hook_raw_image_addr();
1562 }
1563 
1564 void __attribute__((weak)) vid_turn_off_updates()
1565 {
1566 }
1567 
1568 void __attribute__((weak)) vid_turn_on_updates()
1569 {
1570 }
1571 
1572 // use _GetFocusLensSubjectDistance for this on dryos, vx functions are basically equivlent
1573 // not used in CHDK currently for either OS
1574 #ifdef CAM_DRYOS
1575 long __attribute__((weak)) _GetCurrentTargetDistance()
1576 {
1577         return _GetFocusLensSubjectDistance();
1578 }
1579 #endif
1580 
1581 int add_ptp_handler(int opcode, ptp_handler handler, int unknown)
1582 {
1583 #ifdef CAM_CHDK_PTP
1584     return _add_ptp_handler(opcode,handler,unknown);
1585 #else
1586     return 0;
1587 #endif
1588 }
1589 
1590 int CreateTask (const char *name, int prio, int stack_size, void *entry)
1591 {
1592     return _CreateTask(name, prio, stack_size, entry, 0);
1593 }
1594 
1595 void ExitTask()
1596 {
1597     _ExitTask();
1598 }
1599 
1600 // TODO not in sigs for vx yet
1601 #ifndef CAM_DRYOS
1602 void __attribute__((weak)) _reboot_fw_update(const char *fw_update)
1603 {
1604         return;
1605 }
1606 #endif
1607 
1608 #ifdef CAM_DRYOS
1609 int __attribute__((weak)) switch_mode_usb(int mode)
1610 {
1611 #ifdef CAM_CHDK_PTP
1612     if ( mode == 0 ) {
1613         _Rec2PB();
1614         _set_control_event(0x80000000|CAM_USB_EVENTID);
1615     } else if ( mode == 1 ) {
1616         _set_control_event(CAM_USB_EVENTID);
1617         _PB2Rec();
1618     } else return 0;
1619     return 1;
1620 #else
1621   return 0;
1622 #endif // CAM_CHDK_PTP
1623 }
1624 
1625 #else // vxworks
1626 // this doesn't need any special functions so it's defined even without CHDK_CAM_PTP
1627 int __attribute__((weak)) switch_mode_usb(int mode)
1628 {
1629     if ( mode == 0 ) {
1630         // TODO should we revert scriptmode and/or levent? seems to work without
1631         levent_set_play();
1632     } else if ( mode == 1 ) {
1633 #ifdef CAM_USB_EVENTID_VXWORKS
1634         _SetScriptMode(1); // needed to override event
1635         _SetLogicalEventActive(CAM_USB_EVENTID_VXWORKS,0); // set levent "ConnectUSBCable" inactive
1636 #endif
1637         levent_set_record();
1638     } else return 0;
1639     return 1;
1640 }
1641 #endif // vxworks
1642 
1643 /*
1644 // this wrapper isn't currently needed
1645 // 7 calls functions and sets some MMIOs, but doesn't disable caches and actually restart
1646 // 3 skips one function call on some cameras, but does restart
1647 void Restart(unsigned option) {
1648         _Restart(option);
1649 }
1650 */
1651 
1652 unsigned char SetFileAttributes(const char* fn, unsigned char attr)
1653 {
1654 #ifdef CAM_DRYOS_2_3_R39
1655     return _SetFileAttributes(fn, attr);
1656 #else
1657     int fd;
1658     unsigned char ret = -1;
1659     
1660     fd = open(fn, 0, 0);
1661     if( fd ) {
1662         _SetFileAttributes(fd, attr);
1663         close(fd);
1664         ret = attr;
1665     }
1666     return ret;
1667 #endif
1668 }
1669 
1670 // Default implementation of PTP live view functions.
1671 // Override as needed for camera specific variations (see G12/SX30/IXUS310/SX130IS for working examples)
1672 
1673 int __attribute__((weak)) vid_get_viewport_display_xoffset_proper() { return vid_get_viewport_display_xoffset()*2; }
1674 int __attribute__((weak)) vid_get_viewport_display_yoffset_proper() { return vid_get_viewport_display_yoffset(); }
1675 int __attribute__((weak)) vid_get_viewport_buffer_width_proper()    { return 720; }
1676 int __attribute__((weak)) vid_get_viewport_width_proper()           { return vid_get_viewport_width()*2; }
1677 int __attribute__((weak)) vid_get_viewport_height_proper()          { return 240; }
1678 int __attribute__((weak)) vid_get_viewport_fullscreen_height()         { return 240; }
1679 int __attribute__((weak)) vid_get_viewport_fullscreen_width()          { return vid_get_viewport_buffer_width_proper(); }
1680 
1681 int __attribute__((weak)) vid_get_palette_type()                    { return 0; }       // 0 = no palette into, 1 = 16 x 4 byte AYUV values, 
1682                                                                                         // 2 = 16 x 4 byte AYUV (A = 0..3), 3 = 256 x 4 byte AYUV (A = 0..3)
1683 int __attribute__((weak)) vid_get_palette_size()                    { return 0; }
1684 int __attribute__((weak)) vid_get_aspect_ratio()                    { return 0; }       // 0 = 4:3, 1 = 16:9 LCD Aspect Ratio, 2 = 3:2
1685 
1686 void __attribute__((weak)) *vid_get_bitmap_active_buffer()
1687 {
1688   return vid_get_bitmap_fb();   // *** does not get the active buffer! (override if active buffer can be determined)
1689 }
1690 
1691 void __attribute__((weak)) *vid_get_bitmap_active_palette()
1692 {
1693   return 0; // return no palette info unless overridden
1694 }
1695 
1696 // Get active viewport buffer address based on PLAY/REC mode.
1697 // Try to use 'live' buffer in REC mode if vid_get_viewport_live_fb is implemented
1698 // can return NULL in plaback mode, if a video is selected
1699 void *vid_get_viewport_active_buffer()
1700 {
1701   void *p;
1702 
1703   if (camera_info.state.mode_play)
1704   {
1705     p = vid_get_viewport_fb_d();
1706   } else {
1707     p = vid_get_viewport_live_fb();
1708     if ( !p )
1709     {
1710       p = vid_get_viewport_fb();
1711     }
1712   }
1713   
1714   return p;
1715 }
1716 
1717 /*
1718  debug logging function that can be sent to various places
1719  body is ifdef'd inside the body to allow exporting to modules
1720  eventproc version may require System.Create()/SystemEventInit first
1721 */
1722 void dbg_printf(char *fmt,...) {
1723 #ifdef DEBUG_LOGGING
1724     char s[256];
1725     __builtin_va_list va;
1726     __builtin_va_start(va, fmt);
1727     _vsprintf(s, fmt, va);
1728     __builtin_va_end(va);
1729 
1730     // stdout - for use with uart redirection
1731     _ExecuteEventProcedure("Printf",s);
1732     // camera log - will show up in crash dumps, or in stdout on ShowCameraLog
1733     // _LogPrintf(0x120,s);
1734 
1735     // file TODO
1736 #endif
1737 }
1738 
1739 #ifdef CAM_MISSING_RAND
1740 /* Some cameras does not have srand()/rand() functions in firmware, and should be aded here.
1741 E.G. a810/a2300
1742 */
1743 static unsigned int random_variable;
1744 void *_srand(unsigned int seed) {
1745     random_variable = seed;
1746     return (void *) &random_variable;
1747 }
1748 
1749 int _rand(void) {
1750     int value;
1751     value = random_variable*0x41C64E6D+0x3039;
1752     random_variable = value;
1753     value = (0x7FFF & (value>>0x10));
1754     return value;
1755 };
1756 #endif
1757 
1758 //  USB remote high speed timer for pulse width measurement and pulse counting
1759 
1760 extern int _SetHPTimerAfterNow(int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int );
1761 extern int _CancelHPTimer(int);
1762 extern int usb_HPtimer_bad(int, int);
1763 extern int usb_HPtimer_good(int, int);
1764 
1765 int usb_HPtimer_handle=0;
1766 int usb_HPtimer_error_count=0;
1767 
1768 static int ARM_usb_HPtimer_good(int time, int interval) { return usb_HPtimer_good(time, interval); }
1769 static int ARM_usb_HPtimer_bad(int time, int interval) { return usb_HPtimer_bad(time, interval); }
1770 
1771 int start_usb_HPtimer(int interval)            // return 0 if timer already running or error,  1 if successful
1772 {
1773 #ifdef CAM_REMOTE_USB_HIGHSPEED
1774 
1775     if ( usb_HPtimer_handle == 0 )
1776     {
1777         if(interval < CAM_REMOTE_HIGHSPEED_LIMIT) interval=CAM_REMOTE_HIGHSPEED_LIMIT;
1778         usb_HPtimer_handle = _SetHPTimerAfterNow(interval,ARM_usb_HPtimer_good,ARM_usb_HPtimer_bad,interval);
1779         if (!(usb_HPtimer_handle & 0x01)) return 1 ;
1780         usb_HPtimer_handle = 0 ;
1781     }
1782 #endif
1783     return 0;
1784 }
1785 
1786 int stop_usb_HPtimer() 
1787 {
1788 #ifdef CAM_REMOTE_USB_HIGHSPEED
1789     if( usb_HPtimer_handle ) 
1790     {
1791         _CancelHPTimer(usb_HPtimer_handle);
1792         usb_HPtimer_handle = 0 ;
1793         return 1 ;
1794     }
1795 #endif
1796     return 0;
1797 }
1798 
1799 // HP timer functions, callbacks need to be ARM on VxWorks
1800 int SetHPTimerAfterNow(int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int param)
1801 {
1802     return _SetHPTimerAfterNow(delay,good_cb,bad_cb,param);
1803 }
1804 
1805 int CancelHPTimer(int handle)
1806 {
1807     return _CancelHPTimer(handle);
1808 }
1809 
1810 // Override HDMI power on in rec mode for using HDMI Hotplug detect as remote
1811 // note does not disable power if remote turned off or channel changed
1812 // May want to add support for controlling independent of remote as output signal
1813 #ifdef CAM_REMOTE_HDMI_POWER_OVERRIDE
1814 extern void _EnableHDMIPower();
1815 void update_hdmi_power_override()
1816 {
1817     static int oldhdmistate = -1;
1818     if ((camera_info.state.mode_rec == 1) && conf.remote_enable && (conf.remote_input_channel == REMOTE_INPUT_HDMI_HPD))
1819     {
1820         /* if switched to shooting mode and remote using HDMI hotplug is enabled, switch on HDMI Power */
1821         /* just do it once on every change because it needs i2c communication depending on HDMI tranceiver */
1822         if (oldhdmistate != 1)
1823         {
1824             _EnableHDMIPower();
1825         }
1826         oldhdmistate = 1;
1827     }
1828     else
1829     {
1830         oldhdmistate = 0;
1831     }
1832 }
1833 #endif
1834 
1835 // disable camera error(s), E32 is the only error that can be handled at the moment (on newer 'IS' cameras)
1836 #if (OPT_DISABLE_CAM_ERROR)
1837 #warning OPT_DISABLE_CAM_ERROR enabled
1838 void DisableCamError(void)
1839 {
1840     extern void _DisableISDriveError(void);
1841     _DisableISDriveError();
1842 }
1843 #endif
1844 
1845 //---------------------------------------------------------------
1846 // Semaphore & Assert
1847 
1848 void DebugAssert(char *err, int line)
1849 {
1850 #if CAM_3ARG_DebugAssert
1851     extern void _DebugAssert(int, char*, int);
1852     _DebugAssert(0, err, line);
1853 #else
1854     extern void _DebugAssert(char*, int);
1855     _DebugAssert(err, line);
1856 #endif
1857 }
1858 
1859 int CreateBinarySemaphore(char *name, int init)
1860 {
1861     extern int _CreateBinarySemaphore(char*, int);
1862     return _CreateBinarySemaphore(name, init);
1863 }
1864 
1865 int TakeSemaphore(int sem, int timeout)
1866 {
1867     return _TakeSemaphore(sem, timeout);
1868 }
1869 
1870 void GiveSemaphore(int sem)
1871 {
1872     _GiveSemaphore(sem);
1873 }
1874 
1875 //---------------------------------------------------------------

/* [<][>][^][v][top][bottom][index][help] */