apps/php-5.2.1/ext/elphel/elphel_php.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : elphel_php.c
00003 *! DESCRIPTION: Implementation of elphel extension module for PHP
00004 *! Copyright (C) 2002-2007 Elphel, Inc.
00005 *! -----------------------------------------------------------------------------**
00006 *!  This program is free software: you can redistribute it and/or modify
00007 *!  it under the terms of the GNU General Public License as published by
00008 *!  the Free Software Foundation, either version 3 of the License, or
00009 *!  (at your option) any later version.
00010 *!
00011 *!  This program is distributed in the hope that it will be useful,
00012 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *!  GNU General Public License for more details.
00015 *!
00016 *!  You should have received a copy of the GNU General Public License
00017 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 *! -----------------------------------------------------------------------------**
00019 *!  $Log: elphel_php.c,v $
00020 *!  Revision 1.1.1.1  2008/11/27 20:04:02  elphel
00021 *!
00022 *!
00023 *!  Revision 1.28  2008/11/22 05:56:40  elphel
00024 *!  elphel_set_P_arr(), elphel_set_P_value() now return frame number parameters were written to
00025 *!
00026 *!  Revision 1.27  2008/11/20 07:06:04  elphel
00027 *!  just touched to overcome dependency (or lack of its support) to make it notice updated c313a.h
00028 *!
00029 *!  Revision 1.26  2008/11/15 07:04:27  elphel
00030 *!  new parameters to modify analog gains while white balancing
00031 *!
00032 *!  Revision 1.25  2008/11/13 05:40:45  elphel
00033 *!  8.0.alpha16 - modified histogram storage, profiling
00034 *!
00035 *!  Revision 1.24  2008/11/05 02:01:25  elphel
00036 *!  Added bit field manipulation in parameters
00037 *!
00038 *!  Revision 1.23  2008/11/04 17:41:43  elphel
00039 *!  added elphel_gamma(), elphel_reverse_gamma(), elphel_histogram(), elphel_reverse_histogram() functions
00040 *!
00041 *!  Revision 1.22  2008/11/02 07:24:20  elphel
00042 *!  added support for some legacy functions
00043 *!
00044 *!  Revision 1.21  2008/11/02 00:33:02  elphel
00045 *!  Added TODO
00046 *!
00047 *!  Revision 1.20  2008/11/01 06:25:46  elphel
00048 *!  elphel_get_circbuf_pointers() now returns framenumber too
00049 *!
00050 *!  Revision 1.19  2008/10/31 18:26:32  elphel
00051 *!  Adding support for constants like SENSOR_REGS32 (defined constant plus 32 to simplify referencing sensor registers from PHP
00052 *!
00053 *!  Revision 1.18  2008/10/29 04:18:28  elphel
00054 *!  v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
00055 *!
00056 *!  Revision 1.17  2008/10/28 07:05:49  elphel
00057 *!  touched
00058 *!
00059 *!  Revision 1.16  2008/10/25 19:51:06  elphel
00060 *!  Changed word order in writes to gamma tables driver
00061 *!
00062 *!  Revision 1.15  2008/10/23 18:26:14  elphel
00063 *!  Fixed percentile calculations in histograms
00064 *!
00065 *!  Revision 1.14  2008/10/23 08:11:38  elphel
00066 *!  updated for histograms wait queues
00067 *!
00068 *!  Revision 1.13  2008/10/19 06:56:05  elphel
00069 *!  elphel_wait_frame() now works only for compressed frames, new elphel_skip_frames() and elphel_wait_frame_abs() wait sequencer frames (all sensor frames, even those that are not compressed)
00070 *!
00071 *!  Revision 1.12  2008/10/15 22:28:56  elphel
00072 *!  snapshot 8.0.alpha2
00073 *!
00074 *!  Revision 1.11  2008/10/13 16:56:20  elphel
00075 *!  just touched to force recompile
00076 *!
00077 *!  Revision 1.10  2008/10/12 06:13:10  elphel
00078 *!  snapshot
00079 *!
00080 *!  Revision 1.9  2008/10/08 21:26:25  elphel
00081 *!  snapsot 7.2.0.pre4 - first images (actually - second)
00082 *!
00083 *!  Revision 1.8  2008/10/05 05:13:33  elphel
00084 *!  snapshot003
00085 *!
00086 *!  Revision 1.7  2008/10/04 16:10:12  elphel
00087 *!  snapshot
00088 *!
00089 *!  Revision 1.6  2008/09/25 00:58:11  elphel
00090 *!  snapshot
00091 *!
00092 *!  Revision 1.5  2008/09/19 18:06:38  elphel
00093 *!  snapshot
00094 *!
00095 *!  Revision 1.4  2008/09/19 04:37:24  elphel
00096 *!  snapshot
00097 *!
00098 *!  Revision 1.3  2008/09/07 19:48:08  elphel
00099 *!  snapshot
00100 *!
00101 *!  Revision 1.2  2008/06/04 20:07:08  elphel
00102 *!  adding support for multiple frames
00103 *!
00104 *!  Revision 1.21  2008/05/02 15:12:09  elphel
00105 *!  minor comment edit
00106 *!
00107 *!  Revision 1.20  2008/05/01 01:32:04  elphel
00108 *!  support for the frame number - combining hardware frame counter used by i2c (3-bit) and software one
00109 *!
00110 *!  Revision 1.19  2008/04/25 21:31:35  elphel
00111 *!  Added Exif_Photo_ExposureTime to be returned by elphel_get_exif_elphel()
00112 *!
00113 *!  Revision 1.18  2008/04/24 18:16:40  elphel
00114 *!  New function to retrieve circbuf structure (frame pointers and Exif pointers)
00115 *!
00116 *!  Revision 1.17  2008/04/22 22:14:08  elphel
00117 *!  Added functions related to Exif data
00118 *!
00119 *!  Revision 1.16  2008/04/20 06:49:04  elphel
00120 *!  Added histogram related functions
00121 *!
00122 *!  Revision 1.15  2008/04/17 22:36:07  elphel
00123 *!  Bug fix, new function added - elphel_is_compressor_idle()
00124 *!
00125 *!  Revision 1.14  2008/03/20 22:25:09  elphel
00126 *!  elphel_trigger - programming synchronization parameters
00127 *!
00128 *!  Revision 1.13  2008/03/15 23:04:21  elphel
00129 *!  added FPGA registers R/W
00130 *!
00131 *!  Revision 1.12  2008/01/27 06:23:17  elphel
00132 *!  New function - elphel_wait_frame (wait fro the next frame to be compressed)
00133 *!
00134 *!  Revision 1.11  2008/01/12 06:53:23  elphel
00135 *!  7.1.7.2 - added elphel_autoexposure_get() function to elphel php extension
00136 *!
00137 *!  Revision 1.10  2008/01/11 07:47:44  elphel
00138 *!  added elphel_autoexposure_set() function
00139 *!
00140 *!  Revision 1.9  2008/01/10 02:43:37  elphel
00141 *!  Added balance of 2 greens in Bayer mosaic
00142 *!
00143 *!  Revision 1.8  2008/01/09 10:22:02  elphel
00144 *!  Implemented elphel_white_balance() function
00145 *!
00146 *!  Revision 1.7  2007/12/14 22:38:53  elphel
00147 *!  cleaned up after fixing cache bug
00148 *!
00149 *!  Revision 1.6  2007/12/06 19:05:33  elphel
00150 *!  2 new functions - arbitrary compressor command (elphel_compressor_cmd) and elphel_compressor_reset
00151 *!
00152 *!  Revision 1.5  2007/12/05 23:41:04  elphel
00153 *!  Fixing minor in bugs in the sensor reset code
00154 *!
00155 *!  Revision 1.4  2007/12/05 22:01:19  elphel
00156 *!  added handling etrax fs mmap cach problem when communicating between PHP extension and the driver
00157 *!
00158 *!  Revision 1.3  2007/12/04 06:41:11  elphel
00159 *!  Implementation of 2 additional functions:    elphel_get_P_arr, elphel_set_P_arr
00160 *!
00161 */
00162 
00163 #ifdef HAVE_CONFIG_H
00164 #include "config.h"
00165 #endif
00166 
00167 
00168 #include <sys/mman.h>           /* mmap */
00169 #include <sys/ioctl.h>
00170 #include <fcntl.h>     /* (O_RDWR) */
00171 #include <asm/byteorder.h>
00172 #include <errno.h>
00173 #include "php.h"
00174 #include "php_ini.h"  /* for php.ini processing */
00175 #include "elphel_php.h"
00176 
00177 
00178 ZEND_DECLARE_MODULE_GLOBALS(elphel)
00179 static function_entry elphel_functions[] = {
00180     PHP_FE(elphel_get_frame, NULL)
00181     PHP_FE(elphel_skip_frames, NULL)
00182     PHP_FE(elphel_wait_frame_abs, NULL)
00183     PHP_FE(elphel_framepars_get_raw, NULL)
00184     PHP_FE(elphel_parse_P_name, NULL)
00185     PHP_FE(elphel_is_global_par, NULL)
00186     PHP_FE(elphel_is_frame_par, NULL)
00187     PHP_FE(elphel_get_P_value, NULL)
00188     PHP_FE(elphel_set_P_value, NULL)
00189     PHP_FE(elphel_get_P_arr, NULL)
00190     PHP_FE(elphel_set_P_arr, NULL)
00191     PHP_FE(elphel_gamma_add, NULL)
00192     PHP_FE(elphel_gamma_add_custom, NULL)
00193     PHP_FE(elphel_gamma_get, NULL)
00194     PHP_FE(elphel_gamma_get_index, NULL)
00195     PHP_FE(elphel_gamma_get_raw, NULL)
00196     PHP_FE(elphel_histogram_get_raw, NULL)
00197     PHP_FE(elphel_histogram_get, NULL)
00198     PHP_FE(elphel_get_state, NULL)
00199 
00200     PHP_FE(elphel_compressor_reset, NULL)
00201     PHP_FE(elphel_compressor_run, NULL)
00202     PHP_FE(elphel_compressor_stop, NULL)
00203     PHP_FE(elphel_compressor_frame, NULL)
00204     PHP_FE(elphel_reset_sensor, NULL)
00205     PHP_FE(elphel_set_fpga_time, NULL)
00206     PHP_FE(elphel_get_fpga_time, NULL)
00207     PHP_FE(elphel_wait_frame, NULL)
00208     PHP_FE(elphel_fpga_read, NULL)
00209     PHP_FE(elphel_fpga_write, NULL)
00210     PHP_FE(elphel_gamma, NULL)
00211     PHP_FE(elphel_reverse_gamma, NULL)
00212     PHP_FE(elphel_histogram, NULL)
00213     PHP_FE(elphel_reverse_histogram, NULL)
00214     PHP_FE(elphel_get_exif_field, NULL)
00215     PHP_FE(elphel_set_exif_field, NULL)
00216     PHP_FE(elphel_get_interframe_meta, NULL)
00217     PHP_FE(elphel_get_exif_elphel, NULL)
00218     PHP_FE(elphel_update_exif, NULL)
00219     PHP_FE(elphel_get_circbuf_pointers, NULL)
00220     {NULL, NULL, NULL}
00221 };
00222 
00223 zend_module_entry elphel_module_entry = {
00224 #if ZEND_MODULE_API_NO >= 20010901
00225     STANDARD_MODULE_HEADER,
00226 #endif
00227     PHP_ELPHEL_EXTNAME,
00228     elphel_functions,
00229     PHP_MINIT(elphel),
00230     PHP_MSHUTDOWN(elphel),
00231     PHP_RINIT(elphel),
00232     NULL,
00233     PHP_MINFO(elphel),
00234 #if ZEND_MODULE_API_NO >= 20010901
00235     PHP_ELPHEL_VERSION,
00236 #endif
00237     STANDARD_MODULE_PROPERTIES
00238 };
00239 
00240 #ifdef COMPILE_DL_ELPHEL
00241 ZEND_GET_MODULE(elphel)
00242 #endif
00243 
00244 
00245 PHP_INI_BEGIN()
00247 PHP_INI_END()
00248 
00249 
00251 static void init_sens() {
00252 }
00253  
00262 int splitConstantName(char * name) {
00263   int len= strlen(name);
00264   int nIndex;
00265   int d=0;
00266   int dp=1;
00267   int bfields;
00268   int success=0;
00269   if ((len>6) && (name[len-6]=='_') && (name[len-5]=='_')) {
00270 
00271     d= FRAMEPAIR_FRAME_BITS(((name[len-3] - '0') + ((name[len-4] - '0') * 10)), ((name[len-1] - '0') + ((name[len-2] - '0') * 10)));
00272     name[len-6]='\0';
00273     len-=6;
00274     success=1;
00275   }
00276   nIndex= len-1;
00277   while ((nIndex>0) && (name[nIndex]>='0') && (name[nIndex] <='9')){
00278     d+=dp*(name[nIndex]-'0');
00279     dp*=10;
00280     nIndex--;
00281     success=1;
00282   }
00283   nIndex++;
00284   if (success) {
00285     name[nIndex]='\0'; 
00286     return d;
00287   } else return -1;
00288 }
00289 
00291 PHP_FUNCTION(elphel_get_frame)
00292 {
00293     RETURN_LONG( ELPHEL_GLOBALPARS(G_THIS_FRAME));
00294 } 
00295 
00296 PHP_FUNCTION(elphel_skip_frames)
00297 {
00298     long skip=1;
00299     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &skip) == FAILURE) {
00300         RETURN_NULL();
00301     }
00302     long target_frame=lseek((int) ELPHEL_G( fd_fparmsall), 0, SEEK_CUR )+skip;
00303     if ((target_frame<0) || (target_frame > 0x7ffffdff)) RETURN_NULL(); 
00304     RETURN_LONG(lseek((int) ELPHEL_G( fd_fparmsall), target_frame + LSEEK_FRAME_WAIT_ABS, SEEK_END ));
00305 } 
00306 
00307 PHP_FUNCTION(elphel_wait_frame_abs)
00308 {
00309     long target_frame;
00310     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &target_frame) == FAILURE) {
00311         RETURN_NULL();
00312     }
00313     if ((target_frame<0) || (target_frame > 0x7ffffdff)) RETURN_NULL(); 
00314     RETURN_LONG(lseek((int) ELPHEL_G( fd_fparmsall), target_frame + LSEEK_FRAME_WAIT_ABS, SEEK_END ));
00315 } 
00316 
00322 PHP_FUNCTION(elphel_parse_P_name)
00323 {
00324     char full_constant_name[256];
00325     char *name;
00326     int name_len;
00327     long full_addr =-1;
00328     zval const_value;
00329     long constAddNumber;
00330     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
00331       RETURN_NULL();
00332     }
00333     if (strlen(name)>(sizeof(full_constant_name)-8)) RETURN_NULL();
00334     sprintf (full_constant_name,"ELPHEL_%s",name);
00335     if (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC)) { 
00336       full_addr= Z_LVAL(const_value);
00337     } else {
00338       constAddNumber=splitConstantName(full_constant_name);
00339       if ((constAddNumber>=0) && (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC))) {
00340         full_addr= (Z_LVAL(const_value) & ~FRAMEPAIR_MASK_BYTES)+constAddNumber; 
00341        }
00342     }
00343     if (full_addr!=-1) {
00344       RETURN_LONG (full_addr);
00345       zval_dtor(&const_value);
00346     }
00347     RETURN_NULL();
00348 }
00349 
00355 PHP_FUNCTION(elphel_is_global_par)
00356 {
00357     long addr;
00358     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &addr) == FAILURE) {
00359         RETURN_NULL();
00360     }
00361     addr &= 0xffff; 
00362     if ((addr >= FRAMEPAR_GLOBALS) && (addr < (FRAMEPAR_GLOBALS+P_MAX_GPAR))) RETURN_TRUE;
00363     RETURN_FALSE;
00364 }
00365 
00371 PHP_FUNCTION(elphel_is_frame_par)
00372 {
00373     long addr;
00374     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &addr) == FAILURE) {
00375         RETURN_NULL();
00376     }
00377     addr &= 0xffff; 
00378     if (addr < (sizeof (struct framepars_t) >>2)) RETURN_TRUE;
00379     RETURN_FALSE;
00380 }
00381 
00384 PHP_FUNCTION(elphel_get_P_value)
00385 {
00386     long addr, full_addr;
00387     long frame=-1;
00388     long frame_index=-1;
00389     int  frame_stored;
00390     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &full_addr,&frame) == FAILURE) {
00391         RETURN_NULL();
00392     }
00393     if (frame <0) {
00394       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME);
00395     }
00396     addr = full_addr & 0xffff; 
00397 
00398     if (addr >= FRAMEPAR_GLOBALS) { 
00399       if (addr >= (FRAMEPAR_GLOBALS+P_MAX_GPAR)) {
00400         RETURN_NULL();
00401       }
00402       if (full_addr & FRAMEPAIR_MASK_BYTES) {
00403         RETURN_LONG(FRAMEPAIR_FRAME_FIELD(full_addr,ELPHEL_GLOBALPARS(addr)));
00404       } else {
00405         RETURN_LONG(ELPHEL_GLOBALPARS(addr));
00406       }
00407     }
00409     if ((addr<0) ||(addr>= (sizeof (struct framepars_t) >>2))) {
00410       RETURN_NULL();
00411     }
00412     if (frame <0) {
00413 //      frame=ELPHEL_GLOBALPARS(G_THIS_FRAME) + FRAME_DEAFAULT_AHEAD;
00414       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME);  
00415     }
00416 
00418     frame_index = frame & PARS_FRAMES_MASK;
00419     frame_stored= ((struct framepars_t *) ELPHEL_G(framePars))[frame_index].pars[P_FRAME];
00420     if (frame_stored == frame) { 
00421       RETURN_LONG( ((struct framepars_t *) ELPHEL_G(framePars))[frame_index].pars[addr]);
00422     }
00423     if (frame_stored <frame) { 
00424       RETURN_NULL();
00425     }
00427     frame_index = frame & PASTPARS_SAVE_ENTRIES_MASK;
00428     frame_stored= ((struct framepars_past_t *) ELPHEL_G(pastPars))[frame_index].past_pars[P_FRAME-PARS_SAVE_FROM];
00429     if (frame_stored == frame) { 
00430       addr-=PARS_SAVE_FROM;
00431       if ((addr<0) ||(addr>= (sizeof (struct framepars_past_t) >>2))) {
00432         RETURN_NULL();
00433       }
00434       RETURN_LONG( ((struct framepars_past_t *) ELPHEL_G(pastPars))[frame_index].past_pars[addr]);
00435     }
00437     RETURN_NULL();
00438 }
00439 
00443 PHP_FUNCTION(elphel_get_state)
00444 {
00445     long frame8=ELPHEL_GLOBALPARS(G_THIS_FRAME) & PARS_FRAMES_MASK;
00446     long compressor_state= ((struct framepars_t *) ELPHEL_G(framePars))[frame8].pars[P_COMPRESSOR_RUN];
00447     long sensor_state=     ((struct framepars_t *) ELPHEL_G(framePars))[frame8].pars[P_SENSOR_RUN];
00448     long result=(compressor_state==COMPRESSOR_RUN_CONT)?0x8:
00449                 ((compressor_state==COMPRESSOR_RUN_SINGLE)?0xa:
00450                  ((sensor_state==SENSOR_RUN_CONT)?0x7:0));
00451     RETURN_LONG(result);
00452 } 
00453 
00461 PHP_FUNCTION(elphel_framepars_get_raw)
00462 {
00463   char * packed_framepars_structure;
00464   long index=0;
00465   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &index) == FAILURE) {
00466       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong index");
00467       RETURN_NULL ();
00468   }
00469   packed_framepars_structure= (char*) emalloc (sizeof (struct framepars_t));
00470   if (packed_framepars_structure) {
00472      if (index>=0) {
00473        memcpy(packed_framepars_structure, &(((struct framepars_t *) ELPHEL_G(framePars))[index & PARS_FRAMES_MASK]),sizeof(struct framepars_t));
00474      } else if (index == -1) {
00475        memcpy(packed_framepars_structure,   ((struct framepars_t *) ELPHEL_G(funcs2call)),sizeof(struct framepars_t));
00476      } else if (index == -2) {
00477        memcpy(packed_framepars_structure,   ((struct framepars_t *) ELPHEL_G(globalPars)),sizeof(struct framepars_t));
00478      } else RETURN_NULL ();
00479      RETURN_STRINGL (packed_framepars_structure, sizeof(struct framepars_t), 0);
00480   }
00481   php_error_docref(NULL TSRMLS_CC, E_ERROR, "emalloc error");
00482   RETURN_NULL ();
00483 }
00484 
00485 
00486 
00487 
00488 
00496 PHP_FUNCTION(elphel_get_P_arr)
00497 {
00498     long frame=-1;
00499     long frame_index=-1;
00500     int  future=1;
00501     int  frame_stored;
00502     long addr,full_addr,val;
00503     char full_constant_name[256];
00504     zval *arr, **data;
00505     HashTable *arr_hash;
00506     HashPosition pointer;
00507     char *key;
00508     int   key_len;
00509     long index;
00510     long constAddNumber; 
00511     zval const_value;
00512     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &arr, &frame) == FAILURE) {
00513         RETURN_NULL();
00514     }
00515 //    init_sens();
00517     if (frame < 0) { 
00518       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME);
00519     }
00521     frame_index = frame & PARS_FRAMES_MASK;
00522     frame_stored= ((struct framepars_t *) ELPHEL_G(framePars))[frame_index].pars[P_FRAME];
00523     if (frame_stored <frame) { 
00524       future=-1 ; 
00525     }
00526     if (frame_stored > frame) { 
00527       frame_index = frame & PASTPARS_SAVE_ENTRIES_MASK;
00528       frame_stored= ((struct framepars_past_t *) ELPHEL_G(pastPars))[frame_index].past_pars[P_FRAME-PARS_SAVE_FROM];
00529       if (frame_stored != frame) { 
00530          future=-1 ;// not available - only global parameters could be retrieved 
00531       } else future=0; 
00532     }
00533 
00534     array_init(return_value);
00535     arr_hash = Z_ARRVAL_P(arr);
00536     for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
00537         zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;
00538         zend_hash_move_forward_ex(arr_hash, &pointer)) {
00539         if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) {
00540            if (strlen(key)>(sizeof(full_constant_name)-8)) RETURN_NULL();
00541            sprintf (full_constant_name,"ELPHEL_%s",key);
00542            full_addr =-1;
00543            if (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC)) { 
00544               full_addr= Z_LVAL(const_value);
00545            } else {
00546               constAddNumber=splitConstantName(full_constant_name);
00547 //              php_printf ("constAddNumber=%d, full_constant_name=%s (length=%d)\n",constAddNumber, full_constant_name,strlen(full_constant_name));
00548               if ((constAddNumber>=0) && (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC))) { 
00549                 full_addr= (Z_LVAL(const_value) & ~FRAMEPAIR_MASK_BYTES)+constAddNumber; 
00550               }
00551            }
00552            if (full_addr!=-1) {
00553               addr=full_addr & 0xffff;
00555               if (addr >= FRAMEPAR_GLOBALS) {
00556                 if (addr < (FRAMEPAR_GLOBALS+P_MAX_GPAR)) {
00557                   if (full_addr & FRAMEPAIR_MASK_BYTES) {
00558                     add_assoc_long(return_value, key, FRAMEPAIR_FRAME_FIELD(full_addr,ELPHEL_GLOBALPARS(addr)));
00559                   } else {
00560                     add_assoc_long(return_value, key, ELPHEL_GLOBALPARS(addr));
00561                   }
00562                 }
00564               } else if (future>0) {
00565                 if ((addr >=0) && (addr < (sizeof (struct framepars_t) >>2))) {
00566                   if (full_addr & FRAMEPAIR_MASK_BYTES) {
00567                     add_assoc_long(return_value, key, FRAMEPAIR_FRAME_FIELD(full_addr,((struct framepars_t *) ELPHEL_G(framePars))[frame_index].pars[addr]));
00568                   } else {
00569                     add_assoc_long(return_value, key, ((struct framepars_t *) ELPHEL_G(framePars))[frame_index].pars[addr]);
00570                   }
00571                 }
00573               } else if (future==0){
00574                 addr-=PARS_SAVE_FROM;
00575                 if ((addr >=0) && (addr <(sizeof (struct framepars_past_t) >>2))) {
00576                   if (full_addr & FRAMEPAIR_MASK_BYTES) {
00577                     add_assoc_long(return_value, key, FRAMEPAIR_FRAME_FIELD(full_addr,((struct framepars_past_t *) ELPHEL_G(pastPars))[frame_index].past_pars[addr]));
00578                   } else {
00579                     add_assoc_long(return_value, key, ((struct framepars_past_t *) ELPHEL_G(pastPars))[frame_index].past_pars[addr]);
00580                   }
00581                 }
00582               }
00583               zval_dtor(&const_value);
00584            }
00585         }
00586     }
00587 }
00588 
00598 long elphel_set_P_value_common(long addr, long data, long frame, long flags) {
00599     unsigned long write_data[4];
00600     long maddr;
00602     maddr=addr & 0xffff;
00603     if (( (addr & 0xff00) != 0xff00 ) && (maddr >= FRAMEPAR_GLOBALS)) { 
00604       if (maddr >= (FRAMEPAR_GLOBALS+P_MAX_GPAR)) {
00605         return -1;
00606       }
00607       ELPHEL_GLOBALPARS(maddr)=data;
00608       return 0;
00609     }
00610     if (frame <0) {
00611       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME) + FRAME_DEAFAULT_AHEAD;
00612     }
00613     flags |= (flags << 16); 
00614     flags &=0xffff0000;
00615     if ((addr<0) ||((maddr >= (sizeof (struct framepars_t) >>2)) && ( (addr & 0xff00) != 0xff00 )  )) {
00616       return -1;
00617     }
00618     write_data[0]=FRAMEPARS_SETFRAME;
00619     write_data[1]=frame;
00620     write_data[2]= addr | flags;
00621     write_data[3]= data;
00622     long rslt=write(ELPHEL_G(fd_fparmsall), write_data, sizeof(write_data));
00623 //    if (rslt<0) rslt =-errno;
00624     if (rslt<0) return -errno;
00625     if (rslt == sizeof( write_data )) return frame;
00626     return -1;
00627 }
00628 
00629 
00633 
00634 PHP_FUNCTION(elphel_set_P_value)
00635 {
00636     long addr;
00637     long data;
00638     long frame=-1;
00639     unsigned long flags=0;
00640     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|ll", &addr,&data,&frame,&flags) == FAILURE) {
00641       RETURN_NULL();
00642     }
00643     if (((frame=elphel_set_P_value_common (addr, data, frame, flags))) <0) {
00644       RETURN_NULL();
00645     }
00646     RETURN_LONG(frame);
00647 }
00648 
00650 PHP_FUNCTION(elphel_compressor_reset)
00651 {
00652     long frame=-1;
00653     unsigned long flags=-1;
00654     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &frame,&flags) == FAILURE) {
00655       RETURN_NULL();
00656     }
00657     if (flags<0) flags=FRAMEPAIR_FORCE_NEWPROC;
00658     if (((frame=elphel_set_P_value_common (P_COMPRESSOR_RUN, COMPRESSOR_RUN_STOP, frame, flags)))<0) {
00659       RETURN_NULL();
00660     }
00661     RETURN_LONG(frame);
00662 } 
00663 
00665 PHP_FUNCTION(elphel_compressor_run)
00666 {
00667     long frame=-1;
00668     unsigned long flags=-1;
00669     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &frame,&flags) == FAILURE) {
00670       RETURN_NULL();
00671     }
00672     if (flags<0) flags=FRAMEPAIR_FORCE_NEWPROC;
00673     if (((frame=elphel_set_P_value_common (P_COMPRESSOR_RUN, COMPRESSOR_RUN_CONT, frame, flags)))<0) {
00674       RETURN_NULL();
00675     }
00676     RETURN_LONG(frame);
00677 } 
00678 
00680 
00681 PHP_FUNCTION(elphel_compressor_stop)
00682 {
00683     long frame=-1;
00684     unsigned long flags=-1;
00685     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &frame,&flags) == FAILURE) {
00686       RETURN_NULL();
00687     }
00688     if (flags<0) flags=FRAMEPAIR_FORCE_NEWPROC;
00689     if (((frame=elphel_set_P_value_common (P_COMPRESSOR_RUN, COMPRESSOR_RUN_STOP, frame, flags)))<0) {
00690       RETURN_NULL();
00691     }
00692     RETURN_LONG(frame);
00693 }
00694 
00696 PHP_FUNCTION(elphel_compressor_frame)
00697 {
00698     long frame=-1;
00699     unsigned long flags=-1;
00700     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &frame,&flags) == FAILURE) {
00701       RETURN_NULL();
00702     }
00703     if (flags<0) flags=FRAMEPAIR_JUST_THIS;
00704     if (((frame=elphel_set_P_value_common (P_COMPRESSOR_RUN, COMPRESSOR_RUN_SINGLE, frame, flags)))<0) {
00705       RETURN_NULL();
00706     }
00707     RETURN_LONG(frame);
00708 } 
00710 PHP_FUNCTION(elphel_reset_sensor) {
00711   lseek((int) ELPHEL_G(fd_fparmsall), LSEEK_FRAMEPARS_INIT, SEEK_END ); 
00712   elphel_set_P_value_common (P_SENSOR, 0, 0, -1);
00713   RETURN_NULL();
00714 }
00715 
00721 PHP_FUNCTION(elphel_set_P_arr)
00722 {
00723     char full_constant_name[256];
00724     zval *arr, **data;
00725     HashTable *arr_hash;
00726     HashPosition pointer;
00727     char *key;
00728     int   key_len;
00729     long index;
00730     zval const_value;
00731     int array_count;
00732     unsigned long * write_data=NULL;
00733     long frame=-1;
00734     long flags=0;
00735     int num_written=0;
00736     int num_mmap_written=0;
00737     int reg_addr, reg_data, constAddNumber;
00738     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ll", &arr,&frame,&flags) == FAILURE) {
00739         RETURN_LONG(num_written);
00740     }
00741     if (frame <0) {
00742       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME) + FRAME_DEAFAULT_AHEAD;
00743     }
00744     flags |= (flags << 16); 
00745     flags &=0xffff0000;
00746     init_sens();
00747     arr_hash = Z_ARRVAL_P(arr);
00748     array_count = zend_hash_num_elements(arr_hash);
00750     write_data=(unsigned long *) emalloc ((array_count+1)<<3);
00751     if (!write_data) RETURN_NULL(); 
00752 
00753     write_data[0]=FRAMEPARS_SETFRAME;
00754     write_data[1]=frame;
00755     for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
00756         zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;
00757         zend_hash_move_forward_ex(arr_hash, &pointer)) {
00758         if ((zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer) == HASH_KEY_IS_STRING) &&
00759            (Z_TYPE_PP(data) == IS_LONG)) {
00760            reg_data=Z_LVAL_PP(data);
00761            if (strlen(key)>(sizeof(full_constant_name)-8)) RETURN_NULL();
00762            sprintf (full_constant_name,"ELPHEL_%s",key);
00763 
00764            reg_addr =-1;
00765            if (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC)) { 
00766               reg_addr= Z_LVAL(const_value);
00767            } else {
00768               constAddNumber=splitConstantName(full_constant_name);
00769               if ((constAddNumber>=0) && (zend_get_constant(full_constant_name, strlen(full_constant_name), &const_value TSRMLS_CC))) { 
00770                 reg_addr= (Z_LVAL(const_value) & ~FRAMEPAIR_MASK_BYTES)+constAddNumber; 
00771               }
00772            }
00773 
00774            if (reg_addr>=0) {
00776               zval_dtor(&const_value); 
00777               if (((reg_addr & 0xff00) != 0xff00 ) && ((reg_addr & 0xffff) >= FRAMEPAR_GLOBALS)) {  
00778                 if ((reg_addr & 0xffff) < (FRAMEPAR_GLOBALS+P_MAX_GPAR)) { 
00779                   if ((reg_addr & FRAMEPAIR_MASK_BYTES) ==0) { 
00780                     ELPHEL_GLOBALPARS(reg_addr & 0xffff)=reg_data;
00781                     num_mmap_written++;
00782                   } else { 
00783                     write_data[(num_written<<1) + 2]= reg_addr | flags;
00784                     write_data[(num_written<<1) + 3]= reg_data;
00785                     num_written++;
00786                   }
00787                 }
00788               } else if ((reg_addr>=0) && (((reg_addr & 0xffff) < (sizeof (struct framepars_t) >>2)) || ( (reg_addr & 0xff00) == 0xff00 )  )) {
00789                 write_data[(num_written<<1) + 2]= reg_addr | flags;
00790                 write_data[(num_written<<1) + 3]= reg_data;
00791                 num_written++;
00792               }
00793            }
00794         }
00795     }
00796     if (num_written) {
00797       long rslt=write(ELPHEL_G(fd_fparmsall), write_data, (num_written+1)<<3);
00798       efree(write_data);
00799       if (rslt<0) RETURN_LONG(-errno);
00800       num_written=(rslt>>3) -1 ; 
00801     }
00803     RETURN_LONG(frame);
00804 }
00805 
00814 int gamma_calc (double gamma, double black, unsigned short * gtable) {
00815  int i;
00816  double x, black256,k;
00817  int ig;
00818  black256=black*256.0;
00819  if (k>=1.0) k= k/256.0 ; 
00820  if (k>0.99) k=0.99;
00821  k=1.0/(256.0-black256);
00822  if (!gtable) return -1;
00824  if (gamma < 0.13) gamma=0.13;
00825  if (gamma >10.0)  gamma=10.0;
00826  for (i=0; i<257; i++) {
00827    x=k*(i-black256);
00828    if (x < 0.0 ) x=0.0;
00829    ig= 0.5+65535.0*pow(x,gamma);
00830    if (ig > 0xffff) ig=0xffff;
00831    gtable[i]=ig;
00832  }
00833  return 0;
00834 }
00835 
00844 PHP_FUNCTION(elphel_gamma_add)
00845 {
00846     unsigned short data_to_write[260];
00847     double gamma,black;
00848     int igamma, iblack, hash16;
00849     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &gamma, &black ) == FAILURE) {
00850        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong arguments");
00851        RETURN_NULL ();
00852     }
00853     igamma=100*gamma+0.5;
00854     if (igamma <   0) igamma=  0;
00855     if (igamma > 255) igamma=255;
00856     gamma=0.01*igamma;
00857     iblack= (black>=1.0)?black:(256*black+0.5);
00858     if (iblack <   0) iblack=  0;
00859     if (iblack > 254) iblack=254; 
00860     black= (1.0/256.0) * iblack;
00861     hash16= igamma | (iblack<<8);
00862     data_to_write[0]= GAMMA_SCLALE_1; 
00863     data_to_write[1]= hash16;
00866     data_to_write[2]=0;
00867     gamma_calc (gamma, black, &data_to_write[3]);
00868     long rslt=write(ELPHEL_G(fd_gamma_cache), data_to_write, sizeof(data_to_write));
00869     if (rslt<0) {
00870       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Write to fd_gamma_cache returned errno=%d",errno);
00871       RETURN_LONG(-errno);
00872     }
00873     RETURN_LONG (hash16);
00874 }
00875 
00889 PHP_FUNCTION(elphel_gamma_add_custom)
00890 {
00891     unsigned short data_to_write[260];
00892     long  hash16;
00893     int i,d;
00894     zval *arr,  **data;
00895     HashTable *arr_hash;
00896     long array_count;
00897 
00898     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "la", &hash16, &arr ) == FAILURE) {
00899       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong arguments");
00900       RETURN_LONG (-998);
00901     }
00902     arr_hash = Z_ARRVAL_P(arr);
00903     array_count = zend_hash_num_elements(arr_hash);
00904     if (array_count != 257) {
00905       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong array length (should be 257) - %d",array_count);
00906       RETURN_LONG (-999);
00907     }
00908     hash16 &= 0xffff;
00909     data_to_write[0]= GAMMA_SCLALE_1; 
00910     data_to_write[1]= hash16;
00913     data_to_write[2]=0;
00915     for (i=0; i<257; i++) {
00916       if (zend_hash_index_find(arr_hash, i, (void**)&data) == FAILURE) {
00917         php_error_docref(NULL TSRMLS_CC, E_ERROR, "Missing array element [%d]",i);
00918         RETURN_LONG(-i-1000);
00919       }
00920       switch (Z_TYPE_PP(data)) {
00921         case IS_DOUBLE:
00922             d=Z_DVAL_PP(data);
00923             break;
00924         case IS_LONG:
00925             d=(1.0/255)* Z_LVAL_PP(data);
00926         default:
00927           php_error_docref(NULL TSRMLS_CC, E_ERROR, "Non-numeric array element [%d]",i);
00928           RETURN_LONG(-i-2000);
00929       }
00930       if (d<0)   d=0.0;
00931       if (d>1.0) d=1.0;
00932       data_to_write[i+3]=d*65535.0;
00933     }
00934     long rslt=write(ELPHEL_G(fd_gamma_cache), data_to_write, sizeof(data_to_write));
00935     if (rslt<0) {
00936       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Write to fd_gamma_cache returned errno=%d",errno);
00937       RETURN_LONG(-errno);
00938     }
00939     RETURN_LONG (hash16);
00940 }
00941 
00955 PHP_FUNCTION(elphel_gamma_get)
00956 {
00957 //  double scale=1.0;
00958   unsigned short gtable[257];
00959   unsigned short data_to_write[3];
00960   long hash16;
00961   long raw=0;
00962   zval  *zscale=NULL;
00963   int iscale=GAMMA_SCLALE_1;
00964   int gamma_cache_index;
00965   int i;
00966   double gk=1.0/65535.0;
00967   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|zl", &hash16, &zscale,&raw) == FAILURE) {
00968       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong arguments");
00969       RETURN_LONG (-998);
00970   }
00971   if (zscale) {
00972     switch (Z_TYPE_P(zscale)) {
00973         case IS_DOUBLE:
00974             iscale=(GAMMA_SCLALE_1 * Z_DVAL_P(zscale) +0.5);
00975             break;
00976         case IS_LONG:
00977             iscale = Z_LVAL_P(zscale);
00978             break;
00979         default:
00980             php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong scale type");
00981     }
00982   }
00983   if (iscale < 0)      iscale=0;
00984   if (iscale > 0xffff) iscale=0xffff;
00986   data_to_write[0]= iscale; 
00987   data_to_write[1]= hash16;
00990   data_to_write[2]=0;
00991   long rslt=write(ELPHEL_G(fd_gamma_cache), data_to_write, sizeof(data_to_write));
00992   if (rslt<0) {
00993 //      php_error_docref(NULL TSRMLS_CC, E_ERROR, "Write to fd_gamma_cache returned errno=%d",errno);
00994       RETURN_LONG(-errno); 
00995   }
00996   gamma_cache_index= lseek(ELPHEL_G(fd_gamma_cache), 0, SEEK_CUR);
00997   if (!gamma_cache_index) {
00998       RETURN_LONG (-997); 
00999   }
01001   memcpy(gtable, &(((struct gamma_stuct_t *) ELPHEL_G(gamma_cache))[gamma_cache_index].direct[0]),sizeof(gtable));
01002   if (lseek(ELPHEL_G(fd_gamma_cache), LSEEK_GAMMA_ISCURRENT, SEEK_END)<=0) {
01003       RETURN_LONG (-996); 
01004   }
01006   array_init(return_value);
01007   if (raw) for (i=0;i<257;i++)  add_next_index_long  (return_value,    gtable[i]);
01008   else     for (i=0;i<257;i++)  add_next_index_double(return_value, gk*gtable[i]);
01010 }
01011 
01023 PHP_FUNCTION(elphel_gamma_get_index)
01024 {
01025   unsigned short data_to_write[3];
01026   long hash16;
01027   zval  *zscale=NULL;
01028   int iscale=GAMMA_SCLALE_1;
01029   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &hash16, &zscale) == FAILURE) {
01030       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong arguments");
01031       RETURN_LONG (-998);
01032   }
01033   if (zscale) {
01034     switch (Z_TYPE_P(zscale)) {
01035         case IS_DOUBLE:
01036             iscale=(GAMMA_SCLALE_1 * Z_DVAL_P(zscale) +0.5);
01037             break;
01038         case IS_LONG:
01039             iscale = Z_LVAL_P(zscale);
01040             break;
01041         default:
01042             php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong scale type");
01043     }
01044   }
01045   if (iscale < 0)      iscale=0;
01046   if (iscale > 0xffff) iscale=0xffff;
01048   data_to_write[0]= iscale; 
01049   data_to_write[1]= hash16;
01052   data_to_write[2]=0;
01053   long rslt=write(ELPHEL_G(fd_gamma_cache), data_to_write, sizeof(data_to_write));
01054   if (rslt<0) {
01055 //      php_error_docref(NULL TSRMLS_CC, E_ERROR, "Write to fd_gamma_cache returned errno=%d",errno);
01056       RETURN_LONG(-errno); 
01057   }
01058   RETURN_LONG (lseek(ELPHEL_G(fd_gamma_cache), 0, SEEK_CUR));
01059 }
01060 
01061 
01062 
01063 
01071 PHP_FUNCTION(elphel_gamma_get_raw)
01072 {
01073   char * packed_gamma_structure;
01074   long index;
01075   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
01076       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong index");
01077       RETURN_NULL ();
01078   }
01079   if (index >= GAMMA_CACHE_NUMBER) {
01080       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong index (%d >= %d)",index, (int) GAMMA_CACHE_NUMBER);
01081       RETURN_NULL ();
01082   }
01083   packed_gamma_structure= (char*) emalloc (sizeof(struct gamma_stuct_t));
01084   if (packed_gamma_structure) {
01086      memcpy(packed_gamma_structure, &(((struct gamma_stuct_t *) ELPHEL_G(gamma_cache))[index]),sizeof(struct gamma_stuct_t));
01087      if (index==0) { 
01088         packed_gamma_structure[sizeof(struct gamma_stuct_t)-1]=0xff;
01089      }
01090      RETURN_STRINGL (packed_gamma_structure, sizeof(struct gamma_stuct_t), 0);
01091   }
01092   php_error_docref(NULL TSRMLS_CC, E_ERROR, "emalloc error");
01093   RETURN_NULL ();
01094 }
01095 //     memcpy(packed_framepars_structure, &(((struct framepars_t *) ELPHEL_G(framePars))[index]),sizeof(struct framepars_t));
01098 
01106 PHP_FUNCTION(elphel_histogram_get_raw)
01107 {
01108   char * packed_histogram_structure;
01109   long frame=-1;
01110   long needed=0xfff;
01111   long index;
01112   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &needed,&frame) == FAILURE) {
01113       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong index");
01114       RETURN_NULL ();
01115   }
01116   if (frame<0) frame=lseek((int) ELPHEL_G( fd_fparmsall), 0, SEEK_CUR );
01117   needed &= 0xfff;
01118   lseek(ELPHEL_G(fd_histogram_cache), LSEEK_HIST_WAIT_C, SEEK_END); 
01119   lseek(ELPHEL_G(fd_histogram_cache), LSEEK_HIST_NEEDED + (needed & 0xff0), SEEK_END); 
01120   index=lseek(ELPHEL_G(fd_histogram_cache), frame, SEEK_SET);    
01121   if (index <0) {
01122       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Requested histograms are not available (frame=%d, needed=0x%x)",frame,needed);
01123       RETURN_NULL ();
01124   }
01125   if (index >= HISTOGRAM_CACHE_NUMBER) {
01126       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: frame=%d, index=%d",frame, index);
01127       RETURN_NULL ();
01128   }
01129 //  index &= (HISTOGRAM_CACHE_NUMBER -1);
01130   packed_histogram_structure= (char*) emalloc (sizeof(struct histogram_stuct_t));
01131   if (!packed_histogram_structure) {
01132     php_error_docref(NULL TSRMLS_CC, E_ERROR, "emalloc error");
01133     RETURN_NULL ();
01134   }
01136   memcpy(packed_histogram_structure, &(((struct histogram_stuct_t *) ELPHEL_G(histogram_cache))[index]),sizeof(struct histogram_stuct_t));
01137   RETURN_STRINGL (packed_histogram_structure, sizeof(struct histogram_stuct_t), 0);
01138 }
01139 
01153 PHP_FUNCTION(elphel_histogram_get)
01154 {
01155   struct histogram_stuct_t * frame_histogram_structure;
01156   long frame=-1;
01157   long needed=0xfff;
01158   long index;
01159   int i;
01160   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &needed, &frame) == FAILURE) {
01161       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong index");
01162       RETURN_NULL ();
01163   }
01164   needed &= 0xfff;
01165   lseek(ELPHEL_G(fd_histogram_cache), LSEEK_HIST_WAIT_C, SEEK_END); 
01166   lseek(ELPHEL_G(fd_histogram_cache), LSEEK_HIST_NEEDED + (needed & 0xff0), SEEK_END); 
01167   index=lseek(ELPHEL_G(fd_histogram_cache), frame, SEEK_SET);    
01168   if (index <0) {
01169       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Requested histograms are not available (frame=%d, needed=0x%x)",frame,needed);
01170       RETURN_NULL ();
01171   }
01172   if (index >= HISTOGRAM_CACHE_NUMBER) {
01173       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: frame=%d, index=%d",frame, index);
01174       RETURN_NULL ();
01175   }
01176 
01177   frame_histogram_structure= (struct histogram_stuct_t *) emalloc (sizeof(struct histogram_stuct_t));
01178   if (!frame_histogram_structure) {
01179     php_error_docref(NULL TSRMLS_CC, E_ERROR, "emalloc error");
01180     RETURN_NULL ();
01181   }
01183   memcpy((void *) frame_histogram_structure, &(((struct histogram_stuct_t *) ELPHEL_G(histogram_cache))[index]),sizeof(struct histogram_stuct_t));
01185   if (frame != ((struct histogram_stuct_t *) ELPHEL_G(histogram_cache))[index].frame ) {
01186     php_error_docref(NULL TSRMLS_CC, E_ERROR, "Frame changed while retrieving histograms (frame requested=%d, current=%d)",
01187                                               frame, (int)((struct histogram_stuct_t *) ELPHEL_G(histogram_cache))[index].frame);
01188     RETURN_NULL ();
01189     efree (frame_histogram_structure);
01190   }
01192   if ((needed & frame_histogram_structure->valid ) != needed) {
01193     php_error_docref(NULL TSRMLS_CC, E_ERROR, "Not all the requested tables are available (frame=%d needed=0x%x, valid=0x%x)",
01194                                               frame, needed, frame_histogram_structure->valid);
01195     RETURN_NULL ();
01196     efree (frame_histogram_structure);
01197   }
01199 
01200   array_init(return_value);
01201   if (needed & 0x001)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->hist_r[i]);
01202   if (needed & 0x002)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->hist_g[i]);
01203   if (needed & 0x004)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->hist_gb[i]);
01204   if (needed & 0x008)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->hist_b[i]);
01205 
01206   if (needed & 0x010)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->cumul_hist_r[i]);
01207   if (needed & 0x020)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->cumul_hist_g[i]);
01208   if (needed & 0x040)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->cumul_hist_gb[i]);
01209   if (needed & 0x080)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->cumul_hist_b[i]);
01210 
01211   if (needed & 0x100)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->percentile_r[i]);
01212   if (needed & 0x200)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->percentile_g[i]);
01213   if (needed & 0x400)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->percentile_gb[i]);
01214   if (needed & 0x800)  for (i=0;i<256;i++)  add_next_index_long  (return_value,   frame_histogram_structure->percentile_b[i]);
01215 
01216   efree (frame_histogram_structure);
01218 }
01219 
01220 
01222 long createExifDirectory (int rebuild) { 
01223      int indx;
01224      long numfields=0;
01225      struct exif_dir_table_t dir_table_entry;
01227      int exif_this_size=lseek((int) ELPHEL_G(fd_exifdir),1,SEEK_END); // at the beginning of page 1 - position == page length
01228 
01229      if ((ELPHEL_G(exif_size) == exif_this_size) && !rebuild) return 0; // no need to rebuild
01230      ELPHEL_G(exif_size) = exif_this_size;
01231 
01232      for (indx=0; indx<ExifKmlNumber; indx++) ELPHEL_G(exif_dir)[indx].ltag=0;
01233      while (read((int) ELPHEL_G(fd_exifdir), &dir_table_entry, sizeof(dir_table_entry))>0) {
01234        switch (dir_table_entry.ltag) {
01235          case Exif_Image_ImageDescription:      indx= Exif_Image_ImageDescription_Index; break;
01236          case Exif_Image_FrameNumber:           indx= Exif_Image_FrameNumber_Index; break;
01237          case Exif_Photo_DateTimeOriginal:      indx= Exif_Photo_DateTimeOriginal_Index; break;
01238          case Exif_Photo_SubSecTimeOriginal:    indx= Exif_Photo_SubSecTimeOriginal_Index; break;
01239          case Exif_Photo_ExposureTime:          indx= Exif_Photo_ExposureTime_Index; break;
01240          case Exif_GPSInfo_GPSLatitudeRef:      indx= Exif_GPSInfo_GPSLatitudeRef_Index; break;
01241          case Exif_GPSInfo_GPSLatitude:         indx= Exif_GPSInfo_GPSLatitude_Index ; break;
01242          case Exif_GPSInfo_GPSLongitudeRef:     indx= Exif_GPSInfo_GPSLongitudeRef_Index ; break;
01243          case Exif_GPSInfo_GPSLongitude:        indx= Exif_GPSInfo_GPSLongitude_Index; break;
01244          case Exif_GPSInfo_GPSAltitudeRef:      indx= Exif_GPSInfo_GPSAltitudeRef_Index; break;
01245          case Exif_GPSInfo_GPSAltitude:         indx= Exif_GPSInfo_GPSAltitude_Index; break;
01246          case Exif_GPSInfo_GPSTimeStamp:        indx= Exif_GPSInfo_GPSTimeStamp_Index; break;
01247          case Exif_GPSInfo_GPSDateStamp:        indx= Exif_GPSInfo_GPSDateStamp_Index; break;
01248          case Exif_GPSInfo_GPSMeasureMode:      indx= Exif_GPSInfo_GPSMeasureMode_Index; break;
01249          case Exif_GPSInfo_CompassDirectionRef: indx= Exif_GPSInfo_CompassDirectionRef_Index; break;
01250          case Exif_GPSInfo_CompassDirection:    indx= Exif_GPSInfo_CompassDirection_Index; break;
01251          case Exif_GPSInfo_CompassPitchRef:     indx= Exif_GPSInfo_CompassPitchRef_Index; break;
01252          case Exif_GPSInfo_CompassPitch:        indx= Exif_GPSInfo_CompassPitch_Index; break;
01253          case Exif_GPSInfo_CompassRollRef:      indx= Exif_GPSInfo_CompassRollRef_Index; break;
01254          case Exif_GPSInfo_CompassRoll:         indx= Exif_GPSInfo_CompassRoll_Index; break;
01255          default: indx=-1;
01256        }
01257        if (indx>=0) {
01258            memcpy(&(ELPHEL_G(exif_dir)[indx]),&dir_table_entry,sizeof(dir_table_entry));
01259            numfields++;
01260        }
01261      }
01262   return numfields;
01263 }
01264 
01265 
01267 PHP_FUNCTION(elphel_get_circbuf_pointers) {
01268     char * ccam_dma_buf_char= (char *) ELPHEL_G( ccam_dma_buf);
01269     long second=0;
01270     long p,frameParamPointer;
01271     long buff_size=lseek(ELPHEL_G( fd_circ),0,SEEK_END); //size of circbuf
01272     long meta_index,displacementInPage,exifPageStart,frame_be;
01273 
01274     zval *image_pointers;
01275     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &second) == FAILURE) {
01276         RETURN_NULL();
01277     }
01279     createExifDirectory(0); 
01280     if (ELPHEL_G(exif_dir)[Exif_Image_FrameNumber_Index].ltag==Exif_Image_FrameNumber) 
01281       displacementInPage=ELPHEL_G(exif_dir)[Exif_Image_FrameNumber_Index].dst;
01282     else
01283       displacementInPage=-1; 
01284     p=lseek((int) ELPHEL_G( fd_circ), second? LSEEK_CIRC_SCND: LSEEK_CIRC_FIRST, SEEK_END );
01285     if (p<0) RETURN_NULL();
01286     array_init(return_value);
01287     while (p>=0) {
01288       frameParamPointer=p-32;
01289       if (frameParamPointer<0) frameParamPointer+=buff_size;
01290       ALLOC_INIT_ZVAL(image_pointers);
01291       array_init(image_pointers);
01292       add_assoc_long(image_pointers, "circbuf_pointer", p);
01293 //      add_assoc_long(image_pointers, "exif_pointer", ((struct interframe_params_t *) &ccam_dma_buf_char[frameParamPointer])->meta_index);
01294       meta_index=((struct interframe_params_t *) &ccam_dma_buf_char[frameParamPointer])->meta_index;
01295       add_assoc_long(image_pointers, "exif_pointer", meta_index);
01297       if (displacementInPage>=0){
01298         exifPageStart=lseek ((int) ELPHEL_G(fd_exif), meta_index, SEEK_END); 
01299         lseek (ELPHEL_G(fd_exif), exifPageStart+displacementInPage, SEEK_SET);
01300         read(ELPHEL_G(fd_exif), &frame_be, 4);
01302         add_assoc_long(image_pointers, "frame", (long) __cpu_to_be32(frame_be));
01303       }
01304       add_next_index_zval(return_value, image_pointers);
01306       p=lseek((int) ELPHEL_G( fd_circ), LSEEK_CIRC_NEXT, SEEK_END );
01307       p=lseek((int) ELPHEL_G( fd_circ), LSEEK_CIRC_READY, SEEK_END );
01308 
01309     }
01310 }
01311 
01312 
01313 PHP_FUNCTION(elphel_get_interframe_meta)
01314 {
01315    char * ccam_dma_buf_char= (char *) ELPHEL_G( ccam_dma_buf);
01316    struct interframe_params_t frame_params;
01317    long circbuf_pointer=-1;
01318    long frameParamPointer,jpeg_len,timestamp_start;
01319 //   long circbuf_size=ELPHEL_GLOBALPARS(G_CIRCBUFSIZE);
01320    long circbuf_size=ELPHEL_G(ccam_dma_buf_len);
01321    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &circbuf_pointer) == FAILURE) {
01322        RETURN_NULL();
01323    }
01324    frameParamPointer=circbuf_pointer-32;
01325    if (frameParamPointer < 0) frameParamPointer+=circbuf_size;
01326    memcpy (&frame_params, &ccam_dma_buf_char[frameParamPointer],32);
01327    jpeg_len=frame_params.frame_length;
01329    timestamp_start=circbuf_pointer+((jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; 
01330    if (timestamp_start >= circbuf_size) timestamp_start-=circbuf_size;
01331    memcpy (&(frame_params.timestamp_sec), &ccam_dma_buf_char[timestamp_start],8);
01332    if (frame_params.signffff !=0xffff) {
01333      RETURN_NULL();
01334    }
01335    array_init(return_value);
01337    add_assoc_long(return_value, "hash32_r",      frame_params.hash32_r); 
01338    add_assoc_long(return_value, "hash32_g",      frame_params.hash32_g);
01339    add_assoc_long(return_value, "hash32_gb",     frame_params.hash32_gb);
01340    add_assoc_long(return_value, "hash32_b",      frame_params.hash32_b);
01345    add_assoc_long(return_value, "quality2",      frame_params.quality2);
01346    add_assoc_long(return_value, "color",         frame_params.color);      
01347    add_assoc_long(return_value, "byrshift",      frame_params.byrshift);   
01348    add_assoc_long(return_value, "width",         frame_params.width);      
01349    add_assoc_long(return_value, "height",        frame_params.height);     
01350    add_assoc_long(return_value, "meta_index",    frame_params.meta_index); 
01351    add_assoc_long(return_value, "timestamp_sec", frame_params.timestamp_sec);  
01352    add_assoc_long(return_value, "timestamp_usec",frame_params.timestamp_usec); 
01353 }
01354 
01355 
01356 #define saferead255(f,d,l) read(f,d,((l)<256)?(l):255)
01357 PHP_FUNCTION(elphel_get_exif_elphel)
01358 {
01359     long rational3[6];
01360     long exif_page_start;
01361     char *key;
01362     long indx;
01363     char val[256];
01364     long exif_page=0;
01365     int hours=0, minutes=0;
01366     double seconds=0.0;
01367     double  longitude=0.0, latitude=0.0,  altitude=0.0,  heading=0.0,  roll=0.0, pitch=0.0, exposure=0.0;
01368     val[255]='\0';
01369     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &exif_page) == FAILURE) {
01370         RETURN_NULL();
01371     }
01372 
01373     createExifDirectory(0); 
01374     if (exif_page) exif_page_start=lseek ((int) ELPHEL_G(fd_exif), exif_page, SEEK_END); 
01375     else           exif_page_start=lseek ((int) ELPHEL_G(fd_exif), 0, SEEK_SET); 
01376     if (exif_page_start<0) RETURN_NULL(); //exif_page may be out of range
01377     array_init(return_value);
01378 
01379 
01381 
01382      if (ELPHEL_G(exif_dir)[Exif_Image_ImageDescription_Index].ltag==Exif_Image_ImageDescription) { // Exif_Image_ImageDescription is present in template
01383        lseek (ELPHEL_G(fd_exif),
01384               exif_page_start+ELPHEL_G(exif_dir)[Exif_Image_ImageDescription_Index].dst,
01385               SEEK_SET);
01386        saferead255(ELPHEL_G(fd_exif), val, ELPHEL_G(exif_dir)[Exif_Image_ImageDescription_Index].len);
01387        add_assoc_string(return_value, "ImageDescription", val,  1);
01388      }
01390      if (ELPHEL_G(exif_dir)[Exif_Image_FrameNumber_Index].ltag==Exif_Image_FrameNumber) { // Exif_Image_FrameNumber_Index is present in template
01391        lseek (ELPHEL_G(fd_exif),
01392               exif_page_start+ELPHEL_G(exif_dir)[Exif_Image_FrameNumber_Index].dst,
01393               SEEK_SET);
01394        read(ELPHEL_G(fd_exif), rational3, 4);
01395        sprintf (val,"%ld", (long) __cpu_to_be32( rational3[0]));
01396        add_assoc_string(return_value, "FrameNumber", val,  1);
01397      }
01398 
01400      if (ELPHEL_G(exif_dir)[Exif_Photo_DateTimeOriginal_Index].ltag==Exif_Photo_DateTimeOriginal) {
01401        lseek (ELPHEL_G(fd_exif),
01402               exif_page_start+ELPHEL_G(exif_dir)[Exif_Photo_DateTimeOriginal_Index].dst,
01403               SEEK_SET);
01404        read(ELPHEL_G(fd_exif), val, 19);
01405        val[19]='\0';
01406        if (ELPHEL_G(exif_dir)[Exif_Photo_SubSecTimeOriginal_Index].ltag==Exif_Photo_SubSecTimeOriginal) {
01407          val[19]='.';
01408          lseek (ELPHEL_G(fd_exif),
01409                 exif_page_start+ELPHEL_G(exif_dir)[Exif_Photo_SubSecTimeOriginal_Index].dst,
01410                 SEEK_SET);
01411          read(ELPHEL_G(fd_exif), &val[20], 7);
01412          val[27]='\0';
01413        }
01414        add_assoc_string(return_value, "DateTimeOriginal", val,  1);
01415      }
01416 
01418      if (ELPHEL_G(exif_dir)[Exif_Photo_ExposureTime_Index].ltag==Exif_Photo_ExposureTime) { // Exif_Photo_ExposureTime is present in template
01419        lseek (ELPHEL_G(fd_exif),
01420               exif_page_start+ELPHEL_G(exif_dir)[Exif_Photo_ExposureTime_Index].dst,
01421               SEEK_SET);
01422        read(ELPHEL_G(fd_exif), rational3, 8);
01423        exposure=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
01424        sprintf (val,"%f",exposure);
01425        add_assoc_string(return_value, "ExposureTime", val,  1);
01426      }
01427 
01428 
01430      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSMeasureMode_Index].ltag==Exif_GPSInfo_GPSMeasureMode) {
01431        lseek (ELPHEL_G(fd_exif),
01432               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSMeasureMode_Index].dst,
01433               SEEK_SET);
01434        read(ELPHEL_G(fd_exif), val, 1);
01435        add_assoc_stringl(return_value, "GPSMeasureMode", val, 1,  1);
01436      }
01437 
01439      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSDateStamp_Index].ltag==Exif_GPSInfo_GPSDateStamp) {
01440        lseek (ELPHEL_G(fd_exif),
01441               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSDateStamp_Index].dst,
01442               SEEK_SET);
01443        read(ELPHEL_G(fd_exif), val, 10);
01444        val[10]='\0';
01445        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSTimeStamp_Index].ltag==Exif_GPSInfo_GPSTimeStamp) {
01446          lseek (ELPHEL_G(fd_exif),
01447                 exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSTimeStamp_Index].dst,
01448                 SEEK_SET);
01449          read(ELPHEL_G(fd_exif), rational3, 24);
01450          hours=   __cpu_to_be32( rational3[0]);
01451          minutes= __cpu_to_be32( rational3[2]);
01452          seconds= (1.0*(__cpu_to_be32( rational3[4])+1))/__cpu_to_be32( rational3[5]); 
01453          sprintf (&val[10]," %02d:%02d:%05.2f",hours,minutes,seconds);
01454        }
01455        add_assoc_string(return_value, "GPSDateTime", val,  1);
01456      }
01457 
01460      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitude_Index].ltag==Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template
01461        lseek (ELPHEL_G(fd_exif),
01462               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitude_Index].dst,
01463               SEEK_SET);
01464        read(ELPHEL_G(fd_exif), rational3, 24);
01465        longitude=__cpu_to_be32( rational3[0])/(1.0*__cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2])/(60.0*__cpu_to_be32( rational3[3]));
01466        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitudeRef_Index].ltag==Exif_GPSInfo_GPSLongitudeRef) {
01467          lseek (ELPHEL_G(fd_exif),
01468             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLongitudeRef_Index].dst,
01469             SEEK_SET);
01470          read(ELPHEL_G(fd_exif), val, 1);
01471          if (val[0]!= 'E') longitude=-longitude;
01472        }
01473        sprintf (val,"%f",longitude);
01474        add_assoc_string(return_value, "GPSLongitude", val,  1);
01475      }
01477      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitude_Index].ltag==Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template
01478        lseek (ELPHEL_G(fd_exif),
01479               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitude_Index].dst,
01480               SEEK_SET);
01481        read(ELPHEL_G(fd_exif), rational3, 24);
01482        latitude=__cpu_to_be32( rational3[0])/(1.0*__cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2])/(60.0*__cpu_to_be32( rational3[3]));
01483        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitudeRef_Index].ltag==Exif_GPSInfo_GPSLatitudeRef) {
01484          lseek (ELPHEL_G(fd_exif),
01485             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSLatitudeRef_Index].dst,
01486             SEEK_SET);
01487          read(ELPHEL_G(fd_exif), val, 1);
01488          if (val[0] != 'N') latitude=-latitude;
01489         }
01490        sprintf (val,"%f",latitude);
01491        add_assoc_string(return_value, "GPSLatitude", val,  1);
01492      }
01494      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitude_Index].ltag==Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template
01495        lseek (ELPHEL_G(fd_exif),
01496               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitude_Index].dst,
01497               SEEK_SET);
01498        read(ELPHEL_G(fd_exif), rational3, 8);
01499        altitude=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
01500 
01501        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitudeRef_Index].ltag==Exif_GPSInfo_GPSAltitudeRef) {
01502          lseek (ELPHEL_G(fd_exif),
01503             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_GPSAltitudeRef_Index].dst,
01504             SEEK_SET);
01505          read(ELPHEL_G(fd_exif), val, 1);
01506          if (val[0] != '\0') altitude=-altitude;
01507         }
01508        sprintf (val,"%f",altitude);
01509        add_assoc_string(return_value, "GPSAltitude", val,  1);
01510      }
01512      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassDirection_Index].ltag==Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template
01513        lseek (ELPHEL_G(fd_exif),
01514               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassDirection_Index].dst,
01515               SEEK_SET);
01516        read(ELPHEL_G(fd_exif), rational3, 8);
01517        heading=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
01518        sprintf (val,"%f",heading);
01519        add_assoc_string(return_value, "CompassDirection", val,  1);
01520      }
01523      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRoll_Index].ltag==Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template
01524        lseek (ELPHEL_G(fd_exif),
01525               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRoll_Index].dst,
01526               SEEK_SET);
01527        read(ELPHEL_G(fd_exif), rational3, 8);
01528        roll=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
01529 
01530        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRollRef_Index].ltag==Exif_GPSInfo_CompassRollRef) {
01531          lseek (ELPHEL_G(fd_exif),
01532             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassRollRef_Index].dst,
01533             SEEK_SET);
01534          read(ELPHEL_G(fd_exif), val, 1);
01535          if (val[0] != EXIF_COMPASS_ROLL_ASCII[0]) roll=-roll;
01536         }
01537        sprintf (val,"%f",roll);
01538        add_assoc_string(return_value, "CompassRoll", val,  1);
01539      }
01540 
01542      if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitch_Index].ltag==Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template
01543        lseek (ELPHEL_G(fd_exif),
01544               exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitch_Index].dst,
01545               SEEK_SET);
01546        read(ELPHEL_G(fd_exif), rational3, 8);
01547        pitch=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]);
01548 
01549        if (ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitchRef_Index].ltag==Exif_GPSInfo_CompassPitchRef) {
01550          lseek (ELPHEL_G(fd_exif),
01551             exif_page_start+ELPHEL_G(exif_dir)[Exif_GPSInfo_CompassPitchRef_Index].dst,
01552             SEEK_SET);
01553          read(ELPHEL_G(fd_exif), val, 1);
01554          if (val[0] != EXIF_COMPASS_PITCH_ASCII[0]) pitch=-pitch;
01555         }
01556        sprintf (val,"%f",pitch);
01557        add_assoc_string(return_value, "CompassPitch", val,  1);
01558      }
01559 
01560 }
01561 
01562 PHP_FUNCTION(elphel_update_exif) {
01563     RETURN_LONG(createExifDirectory(1)); // force rebuild
01564 }
01565 
01566 
01567 PHP_FUNCTION(elphel_get_exif_field)
01568 {
01569     long exif_page=0;
01570     long ltag;
01571     struct exif_dir_table_t dir_table_entry;
01572     char * rslt;
01573     int found=0;
01574 
01575     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &ltag, &exif_page) == FAILURE) {
01576         RETURN_NULL();
01577     }
01578 // find the ltag in the directory (may need to scan all the directory)
01579     lseek ((int) ELPHEL_G(fd_exifdir), 0, SEEK_SET);
01580     while (read((int) ELPHEL_G(fd_exifdir), &dir_table_entry, sizeof(dir_table_entry))>0) {
01581       if (dir_table_entry.ltag==ltag) {
01582         found=1;
01583         break;
01584       }
01585     }
01586     if (!found) RETURN_NULL();
01587 //    lseek (fd_exifdir, 0, SEEK_SET);
01588     if (exif_page) found= lseek ((int) ELPHEL_G(fd_exif), exif_page, SEEK_END); 
01589     else           found= lseek ((int) ELPHEL_G(fd_exif), 0, SEEK_SET); 
01590     if (found<0) RETURN_NULL(); //exif_page may be out of range
01591 
01592     lseek ((int) ELPHEL_G(fd_exif), dir_table_entry.dst, SEEK_CUR);
01593     rslt=emalloc(dir_table_entry.len);
01594     read((int) ELPHEL_G(fd_exif), rslt, dir_table_entry.len);
01595     RETURN_STRINGL(rslt,dir_table_entry.len,0);
01596 }
01597 
01598 
01599 
01600 PHP_FUNCTION(elphel_set_exif_field)
01601 {
01602     
01603     long ltag;
01604     struct exif_dir_table_t dir_table_entry;
01605     char * value;
01606     int value_length;
01607     int found=0;
01608     
01609     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &ltag, &value,&value_length) == FAILURE) {
01610         RETURN_NULL();
01611     }
01612 // find the ltag in the directory (may need to scan all the directory)
01613     lseek ((int) ELPHEL_G(fd_exifdir), 0, SEEK_SET);
01614     while (read((int) ELPHEL_G(fd_exifdir), &dir_table_entry, sizeof(dir_table_entry))>0) {
01615       if (dir_table_entry.ltag==ltag) {
01616         found=1;
01617         break;
01618       }
01619     }
01620     if (!found) RETURN_NULL();
01621     lseek ((int) ELPHEL_G(fd_exifmeta), dir_table_entry.src, SEEK_SET);
01622     if (value_length>dir_table_entry.len) value_length = dir_table_entry.len;
01624 // php_printf ("value=%s, value_length=%d\n",value, value_length);
01625     long rslt=write(ELPHEL_G(fd_exifmeta), value, value_length);
01626     if (rslt<0) rslt =-errno;
01627     RETURN_LONG(rslt);
01628 }
01629 
01630 
01632 PHP_FUNCTION(elphel_wait_frame)
01633 {
01634     lseek((int) ELPHEL_G( fd_circ), LSEEK_CIRC_TOWP, SEEK_END );
01635     lseek((int) ELPHEL_G( fd_circ), LSEEK_CIRC_WAIT, SEEK_END );
01636     RETURN_NULL();
01637 }
01638 
01648 PHP_FUNCTION(elphel_gamma)
01649 {
01650     long   color;
01651     long frame =-1;
01652     double sensorLevel;
01653     int indx,gamma_index;
01654     unsigned long hash32; 
01655     unsigned long  write_data[2];
01656     int rslt;
01657     unsigned short * gamma_direct;
01658     long lsensorLevel;
01659     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|l", &color, &sensorLevel, &frame ) == FAILURE) {
01660         RETURN_LONG (-1);
01661     }
01662     if ((color <0) || (color > 3)) RETURN_LONG (-1); 
01663     if (frame <0) {
01664       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME)-1;
01665     }
01666 //  php_printf ("frame=0x%lx, color=0x%lx\n",frame, color);
01667     hash32=get_imageParamsThat (P_GTAB_R+color, frame);
01668 //  php_printf ("hash32=0x%lx\n",hash32);
01669     if (hash32 == 0xffffffff) RETURN_LONG (-1);
01671     write_data[0]=hash32;
01672     write_data[1]=0; 
01673     rslt=write(ELPHEL_G(fd_gamma_cache), write_data, 6);
01674 //  php_printf ("frame=0x%lx, write_data[0]=0x%lx, write_data[1]=0x%lx,rslt=0x%x\n",frame, write_data[0], write_data[1],rslt);
01675 
01676     if (rslt<= 0) {
01677       RETURN_LONG (-1);
01678     }
01679    gamma_index=lseek(ELPHEL_G(fd_gamma_cache), 0, SEEK_CUR);
01680 //  php_printf ("gamma_index=0x%x\n",gamma_index);
01681 
01682     if (gamma_index <= 0) {
01683       RETURN_LONG (-2); 
01684     }
01685     gamma_direct= &(((struct gamma_stuct_t *) ELPHEL_G(gamma_cache))[gamma_index].direct[0]);
01686 
01687     lsensorLevel=0x10000*sensorLevel;
01688 //  php_printf ("lsensorLevel=0x%lx\n",lsensorLevel);
01689 
01690     if (lsensorLevel <0) RETURN_LONG (-1);
01691     if (lsensorLevel >0xffff) lsensorLevel=0xffff;
01692 //  php_printf ("(long) gamma_direct[%lx]=0x%lx\n",lsensorLevel>>8, (long) gamma_direct[lsensorLevel>>8]);
01693 //  php_printf ("(long) gamma_direct[%lx]=0x%lx\n",(lsensorLevel>>8)+1, (long) gamma_direct[(lsensorLevel>>8)+1]);
01694 
01695     RETURN_DOUBLE ((1.0/(1<<24))* ((((long) gamma_direct[lsensorLevel>>8])<<8) +
01696                                  (((long) gamma_direct[(lsensorLevel>>8)+1] - ((long) gamma_direct[lsensorLevel>>8]))*(lsensorLevel & 0xff))));
01697 }
01698 
01708 PHP_FUNCTION(elphel_reverse_gamma)
01709 {
01710     long   color;
01711     long   frame=-1;
01712     double gammaLevel;
01713     int indx,gamma_index;
01714     unsigned long hash32; 
01715     unsigned long  write_data[2];
01716     int rslt;
01717     unsigned short * gamma_direct;
01718     unsigned char * gamma_reverse;
01719     long lgammaLevel, sensor_high8,delta, sensor_full;
01720 
01721     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|l", &color, &gammaLevel, &frame ) == FAILURE) {
01722         RETURN_LONG (-1);
01723     }
01724     if ((color <0) || (color > 3)) RETURN_LONG (-1); 
01725     if (frame <0) {
01726       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME)-1;
01727     }
01728     hash32=get_imageParamsThat (P_GTAB_R+color, frame);
01729     if (hash32 == 0xffffffff) RETURN_LONG (-1);
01731     write_data[0]=hash32;
01732     write_data[1]= GAMMA_MODE_NEED_REVERSE;
01733     rslt=write(ELPHEL_G(fd_gamma_cache), write_data, 6);
01734     if (rslt<= 0) {
01735       RETURN_LONG (-1);
01736     }
01737     gamma_index=lseek(ELPHEL_G(fd_gamma_cache), 0, SEEK_CUR);
01738     if (gamma_index <= 0) {
01739       RETURN_LONG (-2); 
01740     }
01741     gamma_direct= &(((struct gamma_stuct_t *) ELPHEL_G(gamma_cache))[gamma_index].direct[0]); 
01742 
01743     gamma_reverse=&(((struct gamma_stuct_t *) ELPHEL_G(gamma_cache))[gamma_index].reverse[0]);
01744 
01745     lgammaLevel=0x10000*gammaLevel;
01746     if (lgammaLevel <0) RETURN_LONG (-1);
01747     if (lgammaLevel >0xffff) lgammaLevel=0xffff;
01748     sensor_high8=gamma_reverse[lgammaLevel >> 8]; 
01749     if (sensor_high8>0) sensor_high8--;                                                     
01750     while ((sensor_high8>0) &&  (gamma_direct[sensor_high8] > lgammaLevel)) sensor_high8--;    
01751     sensor_high8++;
01752     while ((sensor_high8<255) &&  (gamma_direct[sensor_high8] <= lgammaLevel)) sensor_high8++; 
01753     sensor_high8--;
01754     delta=gamma_direct[sensor_high8+1] - gamma_direct[sensor_high8];
01755     if (delta) {
01756       sensor_full=((lgammaLevel-gamma_direct[sensor_high8]) << 8)/delta;
01757     } else sensor_full=0;
01758     sensor_full += sensor_high8 << 8;
01760     if      (sensor_full <      0) sensor_full=0;
01761     else if (sensor_full > 0xffff) sensor_full=0xffff;
01762     RETURN_DOUBLE ((1.0/(1<<16))* sensor_full);
01763 }
01764 
01772 int get_histogram_index (long color,long frame, long needreverse) { 
01773      long hist_index;
01774      if ((color<0) || (color>4))  return -1; 
01775      if (color == COLOR_Y_NUMBER) lseek(ELPHEL_G(fd_histogram_cache), LSEEK_HIST_WAIT_Y, SEEK_END); 
01776      else                         lseek(ELPHEL_G(fd_histogram_cache), LSEEK_HIST_WAIT_C, SEEK_END); 
01777      lseek(ELPHEL_G(fd_histogram_cache), LSEEK_HIST_NEEDED + ((1 << color) << (needreverse? 8:4)), SEEK_END); 
01778      return lseek(ELPHEL_G(fd_histogram_cache), frame, SEEK_SET);                                                       
01779 }
01780 
01787 unsigned long get_imageParamsThat     (int indx, unsigned long frame) {
01788    int frame_index=  frame & PARS_FRAMES_MASK;
01789    int past_index=   frame & PASTPARS_SAVE_ENTRIES_MASK;
01790    unsigned long value;
01792    if (((struct framepars_t *) ELPHEL_G(framePars))[frame_index].pars[P_FRAME] != frame) {
01794      if ((indx < PARS_SAVE_FROM) || (indx >= (PARS_SAVE_FROM+PARS_SAVE_NUM))) return 0xffffffff ; 
01795      value=((struct framepars_past_t *) ELPHEL_G(pastPars))[past_index].past_pars[indx-PARS_SAVE_FROM]; 
01796      if (((struct framepars_past_t *) ELPHEL_G(pastPars))[frame_index].past_pars[P_FRAME-PARS_SAVE_FROM] != frame) { 
01797        return 0xffffffff;
01798      }
01799    } else {
01800      value=((struct framepars_t *) ELPHEL_G(framePars))[frame_index].pars[indx];
01801    }
01802    return value;
01803 }
01804 
01813 PHP_FUNCTION(elphel_histogram)
01814 {
01815     long frame=-1;
01816     long hist_index;
01817     double dlevel;
01818     long   llevel,total_pixels;
01819     unsigned long * hist_cumul;      
01820     long  hist,color;
01821 
01822     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|l", &color, &dlevel, &frame ) == FAILURE) {
01823         RETURN_LONG (-1);
01824     }
01825     if ((color <0) || (color > 3)) RETURN_LONG (-1); 
01826     if (frame <0) {
01827       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME)-1;
01828     }
01829     if (((hist_index=get_histogram_index (color, frame, 0)))<0) RETURN_LONG (-1);
01830     llevel=0x10000*dlevel;
01831     if      (llevel< -0.5) RETURN_LONG(-1) ; 
01832     if      (llevel<0) llevel=0;
01833     else if (llevel>0xffff) llevel=0xffff;
01835     hist_cumul= &(((struct histogram_stuct_t *) ELPHEL_G(histogram_cache))[hist_index].cumul_hist[color<<8]);
01836     total_pixels=  hist_cumul[255];
01837     hist=  (llevel>>8)?hist_cumul[(llevel>>8)-1]:0;
01838     hist +=((hist_cumul[llevel>>8]-hist)*(llevel & 0xff))>>8;
01839     RETURN_DOUBLE(((double) hist)/total_pixels);
01840 }
01841 
01851 PHP_FUNCTION(elphel_reverse_histogram)
01852 {
01853     long frame=-1;
01854     long hist_index;
01855     double fraction;
01856     long   frac_pixels,total_pixels, frac_256, delta;
01857     unsigned long * hist_cumul;      
01858     unsigned char * hist_percentile; 
01859 
01860     long  perc,perc_frac,color;
01861 
01862     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|l", &color, &fraction, &frame ) == FAILURE) {
01863         RETURN_LONG (-1);
01864     }
01865     if ((color <0) || (color > 3)) RETURN_LONG (-1); 
01866     if (frame <0) {
01867       frame=ELPHEL_GLOBALPARS(G_THIS_FRAME)-1;
01868     }
01869     if (((hist_index=get_histogram_index (color, frame, 1)))<0) RETURN_LONG (-1);
01871     hist_cumul= &(((struct histogram_stuct_t *) ELPHEL_G(histogram_cache))[hist_index].cumul_hist[color<<8]);
01872     hist_percentile=&(((struct histogram_stuct_t *) ELPHEL_G(histogram_cache))[hist_index].percentile[color<<8]);
01873     total_pixels=  hist_cumul[255];
01874     frac_pixels=total_pixels*fraction;
01875     if (fraction < -0.5) RETURN_LONG(-1) ; 
01876     if      (frac_pixels<0) frac_pixels=0;
01877     else if (frac_pixels>=total_pixels) frac_pixels=total_pixels-1;
01878     frac_256=(1.0/256)*fraction; 
01879     if (frac_256 > 255) frac_256=255;
01880     perc=hist_percentile[frac_256];
01881     if (perc>0) perc--;                                              
01882     while ((perc>0) &&  (hist_cumul[perc] > frac_pixels)) perc--;    
01883     perc++;
01884     while ((perc<255) &&  (hist_cumul[perc] <= frac_pixels)) perc++; 
01885     perc--;
01886     delta=hist_cumul[perc+1] - hist_cumul[perc];
01887     if (delta) {
01888       perc_frac=((frac_pixels-hist_cumul[perc]) << 8)/delta;
01889     } else perc_frac=0;
01890     perc_frac += perc << 8;
01891     RETURN_DOUBLE((1.0/(1<<16)) * ((double) perc_frac));
01892 }
01893 
01894 
01895 
01897 PHP_FUNCTION(elphel_fpga_read)
01898 {
01899     long addr,data,res;
01900     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &addr) == FAILURE) {
01901         RETURN_NULL();
01902     }
01903     int fd=open("/dev/fpgaio", O_RDONLY);
01904     if (fd<0) {
01905       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/fpgaio");
01906       return ;
01907     }
01908     lseek (fd, addr,SEEK_SET) ; 
01909     res=read(fd,&data,4);
01910     close (fd);
01911     if (res<4) {
01912       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not read file %s","/dev/fpgaio");
01913       return ;
01914     }
01915     RETURN_LONG(data);
01916 }
01917 
01918 PHP_FUNCTION(elphel_fpga_write)
01919 {
01920     long addr,data,res;
01921     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &addr,&data) == FAILURE) {
01922         RETURN_NULL();
01923     }
01924     int fd=open("/dev/fpgaio", O_RDWR);
01925     if (fd<0) {
01926       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/fpgaio");
01927       return ;
01928     }
01929     lseek (fd, addr,SEEK_SET) ; 
01930     res=write(fd,&data,4);
01931     close (fd);
01932     if (res<4) {
01933       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not write to file %s","/dev/fpgaio");
01934       return ;
01935     }
01936     RETURN_NULL();
01937 }
01938 
01939 
01940 
01944 PHP_FUNCTION(elphel_set_fpga_time) {
01945   unsigned long write_data[8]= {FRAMEPARS_SETFRAME,     0,
01946                                 G_SECONDS,              0,
01947                                 G_MICROSECONDS,         0,
01948                                 FRAMEPARS_SETFPGATIME,  0};
01949   double dtime;
01950   long ltime_sec,ltime_usec;
01951   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dtime) == FAILURE) {
01952         RETURN_NULL();
01953   }
01954   ltime_sec=dtime;
01955   ltime_usec=(dtime-ltime_sec)*1000000;
01956   write_data[3]=ltime_sec;
01957   write_data[5]=ltime_usec;
01958 
01959   long rslt=write(ELPHEL_G(fd_fparmsall), write_data, sizeof(write_data));
01960   if (rslt<0) RETURN_LONG(-errno);
01961   dtime=ltime_usec;
01962   dtime=ltime_sec+0.000001*dtime;
01963   RETURN_DOUBLE(dtime);
01964 }
01965 
01967 PHP_FUNCTION(elphel_get_fpga_time) {
01968   double dtime;
01969   long ltime_sec,ltime_usec;
01970   lseek((int) ELPHEL_G( fd_fparmsall), LSEEK_GET_FPGA_TIME, SEEK_END );
01971   dtime= ELPHEL_GLOBALPARS(G_MICROSECONDS);
01972   dtime= ELPHEL_GLOBALPARS(G_SECONDS) + 0.000001*dtime;
01973   RETURN_DOUBLE(dtime);
01974 }
01975 
01976 
01977 static void php_elphel_init_globals(zend_elphel_globals *elphel_globals)
01978 {
01980     elphel_globals->frameParsAll = NULL;
01981     elphel_globals->framePars =    NULL;
01982     elphel_globals->pastPars =     NULL;
01983     elphel_globals->funcs2call=    NULL;
01984     elphel_globals->fd_fparmsall= open("/dev/frameparsall", O_RDWR);
01985     if (elphel_globals->fd_fparmsall <0) {
01986       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/frameparsall");
01987       return ;
01988     }
01990     elphel_globals->frameParsAll = (struct framepars_all_t *) mmap(0, sizeof (struct framepars_all_t) , PROT_READ | PROT_WRITE, MAP_SHARED, elphel_globals->fd_fparmsall, 0);
01991     if((int)elphel_globals->frameParsAll == -1) {
01992       elphel_globals->frameParsAll=NULL;
01993       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in mmap /dev/frameparsall");
01994       close (elphel_globals->fd_fparmsall);
01995       elphel_globals->fd_fparmsall = -1;
01996       return ;
01997     }
01999     elphel_globals->framePars =   elphel_globals->frameParsAll->framePars;
02000     elphel_globals->pastPars =    elphel_globals->frameParsAll->pastPars;
02001     elphel_globals->funcs2call=   elphel_globals->frameParsAll->func2call.pars;
02002     elphel_globals->globalPars =  elphel_globals->frameParsAll->globalPars;
02003 
02004 
02006 
02007     elphel_globals->gamma_cache = NULL;
02008     elphel_globals->fd_gamma_cache= open("/dev/gamma_cache", O_RDWR);
02009     if (elphel_globals->fd_gamma_cache <0) {
02010       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/gamma_cache");
02011       return ;
02012     }
02014     elphel_globals->gamma_cache = (struct gamma_stuct_t *) mmap(0, sizeof (struct gamma_stuct_t) * GAMMA_CACHE_NUMBER , PROT_READ, MAP_SHARED, elphel_globals->fd_gamma_cache, 0);
02015     if((int)elphel_globals->gamma_cache == -1) {
02016       elphel_globals->gamma_cache=NULL;
02017       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in mmap /dev/gamma_cache");
02018       close (elphel_globals->fd_gamma_cache);
02019       elphel_globals->fd_gamma_cache = -1;
02020       return ;
02021     }
02024     elphel_globals->histogram_cache = NULL;
02025     elphel_globals->fd_histogram_cache= open("/dev/histogram_cache", O_RDWR);
02026     if (elphel_globals->fd_histogram_cache <0) {
02027       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/histogram_cache");
02028       return ;
02029     }
02031     elphel_globals->histogram_cache = (struct histogram_stuct_t *) mmap(0, sizeof (struct histogram_stuct_t) * HISTOGRAM_CACHE_NUMBER , PROT_READ, MAP_SHARED, elphel_globals->fd_histogram_cache, 0);
02032     if((int)elphel_globals->histogram_cache == -1) {
02033       elphel_globals->histogram_cache=NULL;
02034       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in mmap /dev/histogram_cache");
02035       close (elphel_globals->fd_histogram_cache);
02036       elphel_globals->fd_histogram_cache = -1;
02037       return ;
02038     }
02039 
02041     elphel_globals->ccam_dma_buf = NULL;
02042     elphel_globals->fd_circ= open("/dev/circbuf", O_RDWR);
02043     if (elphel_globals->fd_circ <0) {
02044       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s","/dev/circbuf");
02045       return ;
02046     }
02047     elphel_globals->ccam_dma_buf_len=lseek(elphel_globals->fd_circ,0,SEEK_END); //size of circbuf
02048 
02050     elphel_globals->ccam_dma_buf = (unsigned long *) mmap(0, elphel_globals->ccam_dma_buf_len , PROT_READ | PROT_WRITE, MAP_SHARED, elphel_globals->fd_circ, 0);
02051     if((int)elphel_globals->ccam_dma_buf == -1) {
02052       elphel_globals->ccam_dma_buf=NULL;
02053       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error in mmap /dev/circbuf");
02054       close (elphel_globals->fd_circ);
02055       elphel_globals->fd_circ = -1;
02056       return ;
02057     }
02058 
02059 
02060     elphel_globals->fd_exif = open(EXIF_DEV_NAME, O_RDONLY);
02061     if (elphel_globals->fd_exif <0) {
02062       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s",EXIF_DEV_NAME);
02063       return ;
02064     }
02065     elphel_globals->fd_exifdir = open(EXIFDIR_DEV_NAME, O_RDONLY);
02066     if (elphel_globals->fd_exifdir <0) {
02067       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s",EXIFDIR_DEV_NAME);
02068       return ;
02069     }
02070     elphel_globals->fd_exifmeta = open(EXIFMETA_DEV_NAME, O_RDWR);
02071     if (elphel_globals->fd_exifmeta <0) {
02072       php_error_docref(NULL TSRMLS_CC, E_ERROR, "Can not open file %s",EXIFMETA_DEV_NAME);
02073       return ;
02074     }
02075     elphel_globals->exif_size=0;
02076 }
02077 
02078 PHP_RINIT_FUNCTION(elphel)
02079 {
02080 // session initialization may be here
02081 
02082     return SUCCESS;
02083 }
02085 PHP_MINIT_FUNCTION(elphel)
02086 {
02087     ZEND_INIT_MODULE_GLOBALS(elphel, php_elphel_init_globals, NULL);
02088 
02089     DEFINE_P_NAMES(pname_arr);
02090 
02091     DEFINE_ONCHANGE_NAMES(onchange_arr);
02092 
02093     DEFINE_LSEEK_NAMES(lseek_arr);
02094 
02095     DEFINE_CONST_NAMES(const_arr);
02096 
02097     int i,j;
02098     char full_constant_name[256];
02099 
02101     REGISTER_INI_ENTRIES(); // not used yet
02102     for (i=0;i< (sizeof(pname_arr)/sizeof(pname_arr[0])); i++) {
02103       if (strlen(pname_arr[i].name)>(sizeof(full_constant_name)-8)) return FAILURE;
02104       sprintf (full_constant_name,"ELPHEL_%s",pname_arr[i].name);
02105       zend_register_long_constant(full_constant_name, strlen(full_constant_name)+1, pname_arr[i].value, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
02106     }
02107 
02108     for (i=0;i< (sizeof(onchange_arr)/sizeof(onchange_arr[0])); i++) {
02109       if (strlen(onchange_arr[i].name)>(sizeof(full_constant_name)-17)) return FAILURE;
02110       sprintf (full_constant_name,"ELPHEL_ONCHANGE_%s",onchange_arr[i].name);
02111       for (j=0; j<strlen(full_constant_name);j++) full_constant_name[j]=toupper(full_constant_name[j]);
02112       zend_register_long_constant(full_constant_name, strlen(full_constant_name)+1, onchange_arr[i].value, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
02113     }
02114 
02115     for (i=0;i< (sizeof(lseek_arr)/sizeof(lseek_arr[0])); i++) {
02116       if (strlen(lseek_arr[i].name)>(sizeof(full_constant_name)-14)) return FAILURE;
02117       sprintf (full_constant_name,"ELPHEL_LSEEK_%s",lseek_arr[i].name);
02118       zend_register_long_constant(full_constant_name, strlen(full_constant_name)+1, lseek_arr[i].value, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
02119     }
02120     for (i=0;i< (sizeof(const_arr)/sizeof(const_arr[0])); i++) {
02121       if (strlen(const_arr[i].name)>(sizeof(full_constant_name)-14)) return FAILURE;
02122       sprintf (full_constant_name,"ELPHEL_CONST_%s",const_arr[i].name);
02123       zend_register_long_constant(full_constant_name, strlen(full_constant_name)+1, const_arr[i].value, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
02124     }
02125     return SUCCESS;
02126 }
02127 
02128 PHP_MSHUTDOWN_FUNCTION(elphel)
02129 {
02130     UNREGISTER_INI_ENTRIES();
02131     if (ELPHEL_G(fd_fparmsall)>=0)       close (ELPHEL_G(fd_fparmsall));
02132     if (ELPHEL_G(fd_gamma_cache)>=0)     close (ELPHEL_G(fd_gamma_cache));
02133     if (ELPHEL_G(fd_histogram_cache)>=0) close (ELPHEL_G(fd_histogram_cache));
02134     if (ELPHEL_G(fd_circ)>=0)            close (ELPHEL_G(fd_circ));
02135     if (ELPHEL_G(fd_exif)>=0)            close (ELPHEL_G(fd_exif));
02136     if (ELPHEL_G(fd_exifdir)>=0)         close (ELPHEL_G(fd_exifdir));
02137     if (ELPHEL_G(fd_exifmeta)>=0)        close (ELPHEL_G(fd_exifmeta));
02138     return SUCCESS;
02139 }
02140 
02141 PHP_MINFO_FUNCTION(elphel)
02142 {
02143      php_info_print_table_start();
02144      php_info_print_table_row(2, "Elphel support", "Enabled");
02145      php_info_print_table_row(2, "Elphel API Version", PHP_ELPHEL_VERSION);
02146      php_info_print_table_end();
02147 }
02148 

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1