00001 /*========================================================================= 00002 | Cheetah Interface Library 00003 |-------------------------------------------------------------------------- 00004 | Copyright (c) 2004-2008 Total Phase, Inc. 00005 | All rights reserved. 00006 | www.totalphase.com 00007 | 00008 | Redistribution and use in source and binary forms, with or without 00009 | modification, are permitted provided that the following conditions 00010 | are met: 00011 | 00012 | - Redistributions of source code must retain the above copyright 00013 | notice, this list of conditions and the following disclaimer. 00014 | 00015 | - Redistributions in binary form must reproduce the above copyright 00016 | notice, this list of conditions and the following disclaimer in the 00017 | documentation and/or other materials provided with the distribution. 00018 | 00019 | - Neither the name of Total Phase, Inc. nor the names of its 00020 | contributors may be used to endorse or promote products derived from 00021 | this software without specific prior written permission. 00022 | 00023 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 | POSSIBILITY OF SUCH DAMAGE. 00035 |-------------------------------------------------------------------------- 00036 | To access Total Phase Cheetah devices through the API: 00037 | 00038 | 1) Use one of the following shared objects: 00039 | cheetah.so -- Linux shared object 00040 | or 00041 | cheetah.dll -- Windows dynamic link library 00042 | 00043 | 2) Along with one of the following language modules: 00044 | cheetah.c/h -- C/C++ API header file and interface module 00045 | cheetah_py.py -- Python API 00046 | cheetah.bas -- Visual Basic 6 API 00047 | cheetah.cs -- C# .NET source 00048 | cheetah_net.dll -- Compiled .NET binding 00049 ========================================================================*/ 00050 00051 00052 /*========================================================================= 00053 | INCLUDES 00054 ========================================================================*/ 00055 /* This #include can be customized to conform to the user's build paths. */ 00056 #include "cheetah.h" 00057 00058 00059 /*========================================================================= 00060 | VERSION CHECK 00061 ========================================================================*/ 00062 #define CH_CFILE_VERSION 0x0300 /* v3.00 */ 00063 #define CH_REQ_SW_VERSION 0x0300 /* v3.00 */ 00064 00065 /* 00066 * Make sure that the header file was included and that 00067 * the version numbers match. 00068 */ 00069 #ifndef CH_HEADER_VERSION 00070 # error Unable to include header file. Please check include path. 00071 00072 #elif CH_HEADER_VERSION != CH_CFILE_VERSION 00073 # error Version mismatch between source and header files. 00074 00075 #endif 00076 00077 00078 /*========================================================================= 00079 | DEFINES 00080 ========================================================================*/ 00081 #define API_NAME "cheetah" 00082 #define API_DEBUG CH_DEBUG 00083 #define API_OK CH_OK 00084 #define API_UNABLE_TO_LOAD_LIBRARY CH_UNABLE_TO_LOAD_LIBRARY 00085 #define API_INCOMPATIBLE_LIBRARY CH_INCOMPATIBLE_LIBRARY 00086 #define API_UNABLE_TO_LOAD_FUNCTION CH_UNABLE_TO_LOAD_FUNCTION 00087 #define API_HEADER_VERSION CH_HEADER_VERSION 00088 #define API_REQ_SW_VERSION CH_REQ_SW_VERSION 00089 00090 00091 /*========================================================================= 00092 | LINUX AND DARWIN SUPPORT 00093 ========================================================================*/ 00094 #if defined(__APPLE_CC__) && !defined(DARWIN) 00095 #define DARWIN 00096 #endif 00097 00098 #if defined(linux) || defined(DARWIN) 00099 00100 #include <stdio.h> 00101 #include <stdlib.h> 00102 #include <unistd.h> 00103 #include <string.h> 00104 #include <fcntl.h> 00105 00106 #ifdef DARWIN 00107 #define DLOPEN_NO_WARN 00108 extern int _NSGetExecutablePath (char *buf, unsigned long *bufsize); 00109 #endif 00110 00111 #include <dlfcn.h> 00112 00113 #define DLL_HANDLE void * 00114 #define MAX_SO_PATH 256 00115 00116 static char SO_NAME[MAX_SO_PATH+1] = API_NAME ".so"; 00117 00118 /* 00119 * These functions allow the Linux behavior to emulate 00120 * the Windows behavior as specified below in the Windows 00121 * support section. 00122 * 00123 * First, search for the shared object in the application 00124 * binary path, then in the current working directory. 00125 * 00126 * Searching the application binary path requires /proc 00127 * filesystem support, which is standard in 2.4.x kernels. 00128 * 00129 * If the /proc filesystem is not present, the shared object 00130 * will not be loaded from the execution path unless that path 00131 * is either the current working directory or explicitly 00132 * specified in LD_LIBRARY_PATH. 00133 */ 00134 static int _checkPath (const char *path) { 00135 char *filename = (char *)malloc(strlen(path) +1 + strlen(SO_NAME) +1); 00136 int fd; 00137 00138 // Check if the file is readable 00139 sprintf(filename, "%s/%s", path, SO_NAME); 00140 fd = open(filename, O_RDONLY); 00141 if (fd >= 0) { 00142 strncpy(SO_NAME, filename, MAX_SO_PATH); 00143 close(fd); 00144 } 00145 00146 // Clean up and exit 00147 free(filename); 00148 return (fd >= 0); 00149 } 00150 00151 static int _getExecPath (char *path, unsigned long maxlen) { 00152 #ifdef linux 00153 return readlink("/proc/self/exe", path, maxlen); 00154 #endif 00155 00156 #ifdef DARWIN 00157 _NSGetExecutablePath(path, &maxlen); 00158 return maxlen; 00159 #endif 00160 } 00161 00162 static void _setSearchPath () { 00163 char path[MAX_SO_PATH+1]; 00164 int count; 00165 char *p; 00166 00167 /* Make sure that SO_NAME is not an absolute path. */ 00168 if (SO_NAME[0] == '/') return; 00169 00170 /* Check the execution directory name. */ 00171 memset(path, 0, sizeof(path)); 00172 count = _getExecPath(path, MAX_SO_PATH); 00173 00174 if (count > 0) { 00175 char *p = strrchr(path, '/'); 00176 if (p == path) ++p; 00177 if (p != 0) *p = '\0'; 00178 00179 /* If there is a match, return immediately. */ 00180 if (_checkPath(path)) return; 00181 } 00182 00183 /* Check the current working directory. */ 00184 p = getcwd(path, MAX_SO_PATH); 00185 if (p != 0) _checkPath(path); 00186 } 00187 00188 #endif 00189 00190 00191 /*========================================================================= 00192 | WINDOWS SUPPORT 00193 ========================================================================*/ 00194 #if defined(WIN32) || defined(_WIN32) 00195 00196 #include <stdio.h> 00197 #include <windows.h> 00198 00199 #define DLL_HANDLE HINSTANCE 00200 #define dlopen(name, flags) LoadLibraryA(name) 00201 #define dlsym(handle, name) GetProcAddress(handle, name) 00202 #define dlerror() "Exiting program" 00203 #define SO_NAME API_NAME ".dll" 00204 00205 /* 00206 * Use the default Windows DLL loading rules: 00207 * 1. The directory from which the application binary was loaded. 00208 * 2. The application's current directory. 00209 * 3a. [Windows NT/2000/XP only] 32-bit system directory 00210 * (default: c:\winnt\System32) 00211 * 3b. 16-bit system directory 00212 * (default: c:\winnt\System or c:\windows\system) 00213 * 4. The windows directory 00214 * (default: c:\winnt or c:\windows) 00215 * 5. The directories listed in the PATH environment variable 00216 */ 00217 static void _setSearchPath () { 00218 /* Do nothing */ 00219 } 00220 00221 #endif 00222 00223 00224 /*========================================================================= 00225 | SHARED LIBRARY LOADER 00226 ========================================================================*/ 00227 /* The error conditions can be customized depending on the application. */ 00228 static void *_loadFunction (const char *name, int *result) { 00229 static DLL_HANDLE handle = 0; 00230 void * function = 0; 00231 00232 /* Load the shared library if necessary */ 00233 if (handle == 0) { 00234 u32 (*version) (void); 00235 u16 sw_version; 00236 u16 api_version_req; 00237 00238 _setSearchPath(); 00239 handle = dlopen(SO_NAME, RTLD_LAZY); 00240 if (handle == 0) { 00241 #if API_DEBUG 00242 fprintf(stderr, "Unable to load %s\n", SO_NAME); 00243 fprintf(stderr, "%s\n", dlerror()); 00244 #endif 00245 *result = API_UNABLE_TO_LOAD_LIBRARY; 00246 return 0; 00247 } 00248 00249 version = (void *)dlsym(handle, "c_version"); 00250 if (version == 0) { 00251 #if API_DEBUG 00252 fprintf(stderr, "Unable to bind c_version() in %s\n", 00253 SO_NAME); 00254 fprintf(stderr, "%s\n", dlerror()); 00255 #endif 00256 handle = 0; 00257 *result = API_INCOMPATIBLE_LIBRARY; 00258 return 0; 00259 } 00260 00261 sw_version = (u16)((version() >> 0) & 0xffff); 00262 api_version_req = (u16)((version() >> 16) & 0xffff); 00263 if (sw_version < API_REQ_SW_VERSION || 00264 API_HEADER_VERSION < api_version_req) 00265 { 00266 #if API_DEBUG 00267 fprintf(stderr, "\nIncompatible versions:\n"); 00268 00269 fprintf(stderr, " Header version = v%d.%02d ", 00270 (API_HEADER_VERSION >> 8) & 0xff, API_HEADER_VERSION & 0xff); 00271 00272 if (sw_version < API_REQ_SW_VERSION) 00273 fprintf(stderr, "(requires library >= %d.%02d)\n", 00274 (API_REQ_SW_VERSION >> 8) & 0xff, 00275 API_REQ_SW_VERSION & 0xff); 00276 else 00277 fprintf(stderr, "(library version OK)\n"); 00278 00279 00280 fprintf(stderr, " Library version = v%d.%02d ", 00281 (sw_version >> 8) & 0xff, 00282 (sw_version >> 0) & 0xff); 00283 00284 if (API_HEADER_VERSION < api_version_req) 00285 fprintf(stderr, "(requires header >= %d.%02d)\n", 00286 (api_version_req >> 8) & 0xff, 00287 (api_version_req >> 0) & 0xff); 00288 else 00289 fprintf(stderr, "(header version OK)\n"); 00290 #endif 00291 handle = 0; 00292 *result = API_INCOMPATIBLE_LIBRARY; 00293 return 0; 00294 } 00295 } 00296 00297 /* Bind the requested function in the shared library */ 00298 function = (void *)dlsym(handle, name); 00299 *result = function ? API_OK : API_UNABLE_TO_LOAD_FUNCTION; 00300 return function; 00301 } 00302 00303 00304 /*========================================================================= 00305 | FUNCTIONS 00306 ========================================================================*/ 00307 static int (*c_ch_find_devices) (int, u16 *) = 0; 00308 int ch_find_devices ( 00309 int num_devices, 00310 u16 * devices 00311 ) 00312 { 00313 if (c_ch_find_devices == 0) { 00314 int res = 0; 00315 if (!(c_ch_find_devices = _loadFunction("c_ch_find_devices", &res))) 00316 return res; 00317 } 00318 return c_ch_find_devices(num_devices, devices); 00319 } 00320 00321 00322 static int (*c_ch_find_devices_ext) (int, u16 *, int, u32 *) = 0; 00323 int ch_find_devices_ext ( 00324 int num_devices, 00325 u16 * devices, 00326 int num_ids, 00327 u32 * unique_ids 00328 ) 00329 { 00330 if (c_ch_find_devices_ext == 0) { 00331 int res = 0; 00332 if (!(c_ch_find_devices_ext = _loadFunction("c_ch_find_devices_ext", &res))) 00333 return res; 00334 } 00335 return c_ch_find_devices_ext(num_devices, devices, num_ids, unique_ids); 00336 } 00337 00338 00339 static Cheetah (*c_ch_open) (int) = 0; 00340 Cheetah ch_open ( 00341 int port_number 00342 ) 00343 { 00344 if (c_ch_open == 0) { 00345 int res = 0; 00346 if (!(c_ch_open = _loadFunction("c_ch_open", &res))) 00347 return res; 00348 } 00349 return c_ch_open(port_number); 00350 } 00351 00352 00353 static Cheetah (*c_ch_open_ext) (int, CheetahExt *) = 0; 00354 Cheetah ch_open_ext ( 00355 int port_number, 00356 CheetahExt * ch_ext 00357 ) 00358 { 00359 if (c_ch_open_ext == 0) { 00360 int res = 0; 00361 if (!(c_ch_open_ext = _loadFunction("c_ch_open_ext", &res))) 00362 return res; 00363 } 00364 return c_ch_open_ext(port_number, ch_ext); 00365 } 00366 00367 00368 static int (*c_ch_close) (Cheetah) = 0; 00369 int ch_close ( 00370 Cheetah cheetah 00371 ) 00372 { 00373 if (c_ch_close == 0) { 00374 int res = 0; 00375 if (!(c_ch_close = _loadFunction("c_ch_close", &res))) 00376 return res; 00377 } 00378 return c_ch_close(cheetah); 00379 } 00380 00381 00382 static int (*c_ch_port) (Cheetah) = 0; 00383 int ch_port ( 00384 Cheetah cheetah 00385 ) 00386 { 00387 if (c_ch_port == 0) { 00388 int res = 0; 00389 if (!(c_ch_port = _loadFunction("c_ch_port", &res))) 00390 return res; 00391 } 00392 return c_ch_port(cheetah); 00393 } 00394 00395 00396 static u32 (*c_ch_unique_id) (Cheetah) = 0; 00397 u32 ch_unique_id ( 00398 Cheetah cheetah 00399 ) 00400 { 00401 if (c_ch_unique_id == 0) { 00402 int res = 0; 00403 if (!(c_ch_unique_id = _loadFunction("c_ch_unique_id", &res))) 00404 return res; 00405 } 00406 return c_ch_unique_id(cheetah); 00407 } 00408 00409 00410 static const char * (*c_ch_status_string) (int) = 0; 00411 const char * ch_status_string ( 00412 int status 00413 ) 00414 { 00415 if (c_ch_status_string == 0) { 00416 int res = 0; 00417 if (!(c_ch_status_string = _loadFunction("c_ch_status_string", &res))) 00418 return 0; 00419 } 00420 return c_ch_status_string(status); 00421 } 00422 00423 00424 static int (*c_ch_version) (Cheetah, CheetahVersion *) = 0; 00425 int ch_version ( 00426 Cheetah cheetah, 00427 CheetahVersion * version 00428 ) 00429 { 00430 if (c_ch_version == 0) { 00431 int res = 0; 00432 if (!(c_ch_version = _loadFunction("c_ch_version", &res))) 00433 return res; 00434 } 00435 return c_ch_version(cheetah, version); 00436 } 00437 00438 00439 static u32 (*c_ch_sleep_ms) (u32) = 0; 00440 u32 ch_sleep_ms ( 00441 u32 milliseconds 00442 ) 00443 { 00444 if (c_ch_sleep_ms == 0) { 00445 int res = 0; 00446 if (!(c_ch_sleep_ms = _loadFunction("c_ch_sleep_ms", &res))) 00447 return res; 00448 } 00449 return c_ch_sleep_ms(milliseconds); 00450 } 00451 00452 00453 static int (*c_ch_target_power) (Cheetah, u08) = 0; 00454 int ch_target_power ( 00455 Cheetah cheetah, 00456 u08 power_flag 00457 ) 00458 { 00459 if (c_ch_target_power == 0) { 00460 int res = 0; 00461 if (!(c_ch_target_power = _loadFunction("c_ch_target_power", &res))) 00462 return res; 00463 } 00464 return c_ch_target_power(cheetah, power_flag); 00465 } 00466 00467 00468 static int (*c_ch_host_ifce_speed) (Cheetah) = 0; 00469 int ch_host_ifce_speed ( 00470 Cheetah cheetah 00471 ) 00472 { 00473 if (c_ch_host_ifce_speed == 0) { 00474 int res = 0; 00475 if (!(c_ch_host_ifce_speed = _loadFunction("c_ch_host_ifce_speed", &res))) 00476 return res; 00477 } 00478 return c_ch_host_ifce_speed(cheetah); 00479 } 00480 00481 00482 static int (*c_ch_dev_addr) (Cheetah) = 0; 00483 int ch_dev_addr ( 00484 Cheetah cheetah 00485 ) 00486 { 00487 if (c_ch_dev_addr == 0) { 00488 int res = 0; 00489 if (!(c_ch_dev_addr = _loadFunction("c_ch_dev_addr", &res))) 00490 return res; 00491 } 00492 return c_ch_dev_addr(cheetah); 00493 } 00494 00495 00496 static int (*c_ch_spi_bitrate) (Cheetah, int) = 0; 00497 int ch_spi_bitrate ( 00498 Cheetah cheetah, 00499 int bitrate_khz 00500 ) 00501 { 00502 if (c_ch_spi_bitrate == 0) { 00503 int res = 0; 00504 if (!(c_ch_spi_bitrate = _loadFunction("c_ch_spi_bitrate", &res))) 00505 return res; 00506 } 00507 return c_ch_spi_bitrate(cheetah, bitrate_khz); 00508 } 00509 00510 00511 static int (*c_ch_spi_configure) (Cheetah, CheetahSpiPolarity, CheetahSpiPhase, CheetahSpiBitorder, u08) = 0; 00512 int ch_spi_configure ( 00513 Cheetah cheetah, 00514 CheetahSpiPolarity polarity, 00515 CheetahSpiPhase phase, 00516 CheetahSpiBitorder bitorder, 00517 u08 ss_polarity 00518 ) 00519 { 00520 if (c_ch_spi_configure == 0) { 00521 int res = 0; 00522 if (!(c_ch_spi_configure = _loadFunction("c_ch_spi_configure", &res))) 00523 return res; 00524 } 00525 return c_ch_spi_configure(cheetah, polarity, phase, bitorder, ss_polarity); 00526 } 00527 00528 00529 static int (*c_ch_spi_queue_clear) (Cheetah) = 0; 00530 int ch_spi_queue_clear ( 00531 Cheetah cheetah 00532 ) 00533 { 00534 if (c_ch_spi_queue_clear == 0) { 00535 int res = 0; 00536 if (!(c_ch_spi_queue_clear = _loadFunction("c_ch_spi_queue_clear", &res))) 00537 return res; 00538 } 00539 return c_ch_spi_queue_clear(cheetah); 00540 } 00541 00542 00543 static int (*c_ch_spi_queue_oe) (Cheetah, u08) = 0; 00544 int ch_spi_queue_oe ( 00545 Cheetah cheetah, 00546 u08 oe 00547 ) 00548 { 00549 if (c_ch_spi_queue_oe == 0) { 00550 int res = 0; 00551 if (!(c_ch_spi_queue_oe = _loadFunction("c_ch_spi_queue_oe", &res))) 00552 return res; 00553 } 00554 return c_ch_spi_queue_oe(cheetah, oe); 00555 } 00556 00557 00558 static int (*c_ch_spi_queue_delay_cycles) (Cheetah, int) = 0; 00559 int ch_spi_queue_delay_cycles ( 00560 Cheetah cheetah, 00561 int cycles 00562 ) 00563 { 00564 if (c_ch_spi_queue_delay_cycles == 0) { 00565 int res = 0; 00566 if (!(c_ch_spi_queue_delay_cycles = _loadFunction("c_ch_spi_queue_delay_cycles", &res))) 00567 return res; 00568 } 00569 return c_ch_spi_queue_delay_cycles(cheetah, cycles); 00570 } 00571 00572 00573 static int (*c_ch_spi_queue_delay_ns) (Cheetah, int) = 0; 00574 int ch_spi_queue_delay_ns ( 00575 Cheetah cheetah, 00576 int nanoseconds 00577 ) 00578 { 00579 if (c_ch_spi_queue_delay_ns == 0) { 00580 int res = 0; 00581 if (!(c_ch_spi_queue_delay_ns = _loadFunction("c_ch_spi_queue_delay_ns", &res))) 00582 return res; 00583 } 00584 return c_ch_spi_queue_delay_ns(cheetah, nanoseconds); 00585 } 00586 00587 00588 static int (*c_ch_spi_queue_ss) (Cheetah, u08) = 0; 00589 int ch_spi_queue_ss ( 00590 Cheetah cheetah, 00591 u08 active 00592 ) 00593 { 00594 if (c_ch_spi_queue_ss == 0) { 00595 int res = 0; 00596 if (!(c_ch_spi_queue_ss = _loadFunction("c_ch_spi_queue_ss", &res))) 00597 return res; 00598 } 00599 return c_ch_spi_queue_ss(cheetah, active); 00600 } 00601 00602 00603 static int (*c_ch_spi_queue_byte) (Cheetah, int, u08) = 0; 00604 int ch_spi_queue_byte ( 00605 Cheetah cheetah, 00606 int count, 00607 u08 data 00608 ) 00609 { 00610 if (c_ch_spi_queue_byte == 0) { 00611 int res = 0; 00612 if (!(c_ch_spi_queue_byte = _loadFunction("c_ch_spi_queue_byte", &res))) 00613 return res; 00614 } 00615 return c_ch_spi_queue_byte(cheetah, count, data); 00616 } 00617 00618 00619 static int (*c_ch_spi_queue_array) (Cheetah, int, const u08 *) = 0; 00620 int ch_spi_queue_array ( 00621 Cheetah cheetah, 00622 int num_bytes, 00623 const u08 * data_out 00624 ) 00625 { 00626 if (c_ch_spi_queue_array == 0) { 00627 int res = 0; 00628 if (!(c_ch_spi_queue_array = _loadFunction("c_ch_spi_queue_array", &res))) 00629 return res; 00630 } 00631 return c_ch_spi_queue_array(cheetah, num_bytes, data_out); 00632 } 00633 00634 00635 static int (*c_ch_spi_batch_length) (Cheetah) = 0; 00636 int ch_spi_batch_length ( 00637 Cheetah cheetah 00638 ) 00639 { 00640 if (c_ch_spi_batch_length == 0) { 00641 int res = 0; 00642 if (!(c_ch_spi_batch_length = _loadFunction("c_ch_spi_batch_length", &res))) 00643 return res; 00644 } 00645 return c_ch_spi_batch_length(cheetah); 00646 } 00647 00648 00649 static int (*c_ch_spi_batch_shift) (Cheetah, int, u08 *) = 0; 00650 int ch_spi_batch_shift ( 00651 Cheetah cheetah, 00652 int num_bytes, 00653 u08 * data_in 00654 ) 00655 { 00656 if (c_ch_spi_batch_shift == 0) { 00657 int res = 0; 00658 if (!(c_ch_spi_batch_shift = _loadFunction("c_ch_spi_batch_shift", &res))) 00659 return res; 00660 } 00661 return c_ch_spi_batch_shift(cheetah, num_bytes, data_in); 00662 } 00663 00664 00665 static int (*c_ch_spi_async_submit) (Cheetah) = 0; 00666 int ch_spi_async_submit ( 00667 Cheetah cheetah 00668 ) 00669 { 00670 if (c_ch_spi_async_submit == 0) { 00671 int res = 0; 00672 if (!(c_ch_spi_async_submit = _loadFunction("c_ch_spi_async_submit", &res))) 00673 return res; 00674 } 00675 return c_ch_spi_async_submit(cheetah); 00676 } 00677 00678 00679 static int (*c_ch_spi_async_collect) (Cheetah, int, u08 *) = 0; 00680 int ch_spi_async_collect ( 00681 Cheetah cheetah, 00682 int num_bytes, 00683 u08 * data_in 00684 ) 00685 { 00686 if (c_ch_spi_async_collect == 0) { 00687 int res = 0; 00688 if (!(c_ch_spi_async_collect = _loadFunction("c_ch_spi_async_collect", &res))) 00689 return res; 00690 } 00691 return c_ch_spi_async_collect(cheetah, num_bytes, data_in); 00692 } 00693 00694