drivers/cfontz/cfontz.c

00001 /*
00002  * Copyright Ian Burnett 2005, 2006.
00003  *
00004  * This file is part of Ian's Interactive LCD controller (IILC).
00005  * 
00006  * IILC is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU General Public License as published by the Free
00008  * Software Foundation; either version 2 of the License, or (at your
00009  * option) any later version.
00010  *
00011  * IILC is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00014  * for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with IILC; if not, write to the Free Software Foundation, Inc.,
00018  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
00019  */
00020 
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <string.h>
00024 
00025 #if defined(_WIN32)
00026 #   include "pthread_w32.h"
00027 #   include "time_w32.h"
00028 #else
00029 #endif
00030 
00031 #include "lcd.h"
00032 #include "trace.h"
00033 #include "packet.h"
00034 #include "driver.h"
00035 #include "cfontz.h"
00036 
00037 
00038 #define IILC_MODULE MODULE_TYPE_PACKET
00039 
00040 
00041 /*
00042  * Strings which the various CF displays report back their
00043  * types as.
00044  */
00045 
00046 #define CFONTZ_CFA633_STRING "CFA633"
00047 #define CFONTZ_CFA635_STRING "CFA635"
00048 
00049 
00050 
00051 static int cfontz_WritePacket(LP_CFONTZ_DEV_INSTANCE pDevice,
00052                               LPPACKET pPacket, 
00053                               LPPACKET * ppReplyPacket);
00054 
00055 static int cfontz_UpdateFanReport(LP_CFONTZ_DEV_INSTANCE pInst);
00056 
00057 static int cfontz_UpdateTempReport(LP_CFONTZ_DEV_INSTANCE pInst);
00058 
00059 static int cfontz_UpdateFanPower(LP_CFONTZ_DEV_INSTANCE pInst);
00060 
00061 static int cfontz_UpdateKeyReport(LP_CFONTZ_DEV_INSTANCE pInst);
00062 
00063 static int cfontz_ReceiveTempReport(LP_CFONTZ_DEV_INSTANCE pInst, 
00064                                     LPPACKET pPacket);
00065 
00066 static int cfontz_ReceiveFanSpeedReport(LP_CFONTZ_DEV_INSTANCE pInst,
00067                                         LPPACKET pPacket);
00068 
00069 static int cfontz_ReceiveKeyPressReport(LP_CFONTZ_DEV_INSTANCE pInst, 
00070                                         LPPACKET pPacket);
00071 
00072 /*
00073 
00074 static int cfontz_SetCallbackKeyEvent(LP_CFONTZ_DEV_INSTANCE pInst, 
00075                                       pfnKeyEventListener pfn, 
00076                                       void * context);
00077 
00078 */
00079 
00080 static int cfontz_InitDeviceType(LP_CFONTZ_DEV_INSTANCE pInst,
00081                                  const char * pszVersionString);
00082 
00083 
00084 static void * RxThread(void * arg);
00085 
00086 static int cfontz_detectSCAB(LP_CFONTZ_DEV_INSTANCE pInst);
00087 
00088 
00089 
00090 /****************************************************************************/
00091 /*                                                                          */
00092 /* Functions which constitute the exported API for the driver module.       */
00093 /*                                                                          */
00094 /****************************************************************************/
00095 
00096 
00097 int driver_Create(const char * pszPort, LP_DRIVER_FN_ARRAY pFnArray, 
00098                   LP_DRIVER_INSTANCE * ppDriverInstData)
00099 {
00100     int rc = 0;
00101     LP_CFONTZ_DEV_INSTANCE pInst = NULL;
00102 
00103     int i = 0;
00104     char pszVersionInfo[MAX_DATA_LENGTH + 1];
00105     LPPACKET pPacket = NULL, pReplyPacket = NULL;
00106 
00107     IILC_TRACE_ENTRY(IILC_MODULE, T_driver_Create);
00108     traceDebug(IILC_TRACE_CONTEXT,
00109         "pszPort %p, pFnArray %p, ppDevice %p", pszPort, pFnArray, ppDriverInstData);
00110 
00111     /* Sanity check */
00112     if (pszPort == NULL || pFnArray == NULL || ppDriverInstData == NULL) {
00113         traceError(IILC_TRACE_CONTEXT, "Input parameter NULL");
00114         rc = ERR_BAD_PARAMETER;
00115         goto end_of_function;
00116     }
00117 
00118     traceDebug(IILC_TRACE_CONTEXT, "Creating CrystalFontz device on port [%s]", pszPort);
00119 
00120     /* Allocate the main memory with simple clear */
00121     pInst = (LP_CFONTZ_DEV_INSTANCE) calloc(1, sizeof(CFONTZ_DEV_INSTANCE));
00122 
00123     /*
00124      * More complicated init
00125      */
00126 
00127     /* Take a copy of the port string */
00128     pInst->pszPort = (char *) malloc(strlen(pszPort) + 1);
00129     strcpy(pInst->pszPort, pszPort);
00130 
00131     /*
00132      * Setup the threads and sync primitives
00133      */
00134 
00135     /* Must wait to init RxThreadID later */
00136 
00137     /* Mutex to lock when waiting for an Rx packet */
00138     pthread_mutex_init(&(pInst->RxMutex), NULL);
00139 
00140     /* Semaphore on which to wait when waiting for an Rx packet */
00141     pthread_cond_init(&(pInst->RxSemaphore), NULL);
00142 
00143     /* Flag to indicate the Rx thread should stay running */
00144     pInst->RxRunning = 1;
00145 
00146     /* Mutex to lock while the Rx thread is runnning */
00147     pthread_mutex_init(&(pInst->RunningMutex), NULL);
00148 
00149     /*
00150      * Callback information
00151      */
00152 
00153     /* Function pointer block */
00154     pInst->pfn.FanSpeed = NULL;
00155     pInst->pfn.KeyEvent = NULL;
00156     pInst->pfn.Temp     = NULL;
00157 
00158     /* Context info block */
00159     pInst->context.FanSpeed = NULL;
00160     pInst->context.KeyEvent = NULL;
00161     pInst->context.Temp     = NULL;
00162 
00163 /***************************************************************/
00164 
00165     /* Update the function pointers */
00166     pFnArray->Dispose       = driver_Dispose;
00167     pFnArray->Start         = driver_Start;
00168     pFnArray->Stop          = driver_Stop;
00169     pFnArray->SetBacklight  = driver_SetBacklight;
00170     pFnArray->GetScreenSize = driver_GetScreenSize;
00171     pFnArray->SetFanPower   = driver_SetFanPower;
00172     pFnArray->WriteText     = driver_WriteText;
00173     pFnArray->EnableFanReport = driver_EnableFanReport;
00174     pFnArray->DisableFanReport = driver_DisableFanReport;
00175     pFnArray->SetCallbackFan = driver_SetCallbackFan;
00176     pFnArray->SetContrast    = driver_SetContrast;
00177     pFnArray->EnableTempReport = driver_EnableTempReport;
00178     pFnArray->DisableTempReport = driver_DisableTempReport;
00179     pFnArray->SetCallbackTemp = driver_SetCallbackTemp;
00180 
00181     /*
00182      * Data structure init complete - now start doing some work to get this
00183      * unit running
00184      */
00185 
00186     /* Perform OS-specific init to physical device */
00187     rc = cfontz_InitDevice(pInst);
00188     if (rc) {
00189         goto end_of_function;
00190     }
00191 
00192     /* Pause required to allow device to initialise */
00193     SLEEP(350);
00194 
00195     /* Spin off a receiving thread */
00196     rc = pthread_create(&(pInst->RxThreadID), NULL, RxThread, (void *) pInst);
00197     if (rc) {
00198         traceError(IILC_TRACE_CONTEXT, "pthread_create error %d (%s)\n", errno, strerror(errno));
00199         goto end_of_function;
00200     }
00201 
00202     /*
00203      * Send a command up to the display to get the hardware version
00204      */
00205     
00206     /* Create named packet type with no data */
00207     packetCreate(PACKET_TYPE_GET_VERSION_INFO, &pPacket);
00208     cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00209     packetDispose(&pPacket);
00210 
00211     /* Check the return packet */
00212     if (pReplyPacket != NULL) {
00213         if (packetGetClass(pReplyPacket) != PACKET_CLASS_NORMAL_RESPONSE) {
00214             traceError(IILC_TRACE_CONTEXT, "Invalid response to hardware version request");
00215         }
00216     }
00217     else {
00218         traceError(IILC_TRACE_CONTEXT, "No response to hardware version request");
00219     }
00220 
00221 
00222     /* Zap data buffer to NULLs */
00223     memset((void *) pszVersionInfo, 0, MAX_DATA_LENGTH + 1);
00224 
00225     /* Get the hardware string */
00226     while (packetReadData(pReplyPacket, (unsigned char *) &pszVersionInfo[i++]) != ERR_END_OF_PACKET);
00227 
00228     /* Dump out the hardware version info */
00229     traceDebug(IILC_TRACE_CONTEXT, "Connected to CrystalFontz hardware [%s]", pszVersionInfo);
00230 
00231     /* Now try to programmatically work out what we're connected to */
00232     rc = cfontz_InitDeviceType(pInst, pszVersionInfo);
00233     if (rc) { goto end_of_function; }
00234 
00235     /* Create the fan power array */
00236     if (pInst->nFanCount > 0) {
00237 
00238         /* All fans default to 100% power */
00239         pInst->nFanPower = (unsigned int *) calloc(pInst->nFanCount, sizeof(unsigned int));
00240         for (i = 0; i < pInst->nFanCount; i++) {
00241             pInst->nFanPower[i] = 100;
00242         }
00243     }
00244 
00245     /*
00246     {
00247         char * envVar = NULL;
00248         unsigned int nPower = 100;
00249 
00250         envVar = getenv("FANPOWER");
00251         if (envVar != NULL) {
00252             nPower = atoi(envVar);
00253         }
00254         else {
00255             printf("FANPOWER env var not set\n");
00256         }
00257 
00258         driver_SetFanPower((LP_DRIVER_INSTANCE) pInst, 0, nPower);
00259     }
00260     */
00261 
00262     /* All OK - assign to caller's data area */
00263     *ppDriverInstData = (LP_DRIVER_INSTANCE) pInst;    
00264 
00265 end_of_function:
00266 
00267     IILC_TRACE_EXIT_RC(rc);
00268     return rc;
00269 
00270 }
00271 
00272 int cfontz_detectSCAB(LP_CFONTZ_DEV_INSTANCE pInst)
00273 {
00274     int rc = 0;
00275 
00276     unsigned char gpio = 0;
00277     unsigned char state = 0;
00278 
00279     LPPACKET pPacket = NULL, pReplyPacket = NULL;
00280 
00281     /* Assume not present */
00282     pInst->bSCABPresent = 0;
00283 
00284     /* Taken from the "Detecting SCAB" thread post dated 10-04-2005 11:05 PM,
00285      * found in the "Product questions" forum.
00286      *
00287      * Since the SCAB has a 1K pull-up on GPIO[4] (the DOW line) it should be
00288      * possible to use that to detect if it is connected:
00289      *
00290      * 1) set GPIO[4] to drive high, pull low
00291      * 2) drive it low (meaning it is pulled low by the internal 5K)
00292      * 3) read it. If it is low, then no SCAB is attached, if it is high
00293      *    (1K SCAB pull-up swamping internal 5K pull-down) then a SCAB is
00294      *    attached.
00295      * 4) restore GPIO[4]'s port state.
00296      */
00297 
00298     /* Configure GPIO[4] */
00299     packetCreate(PACKET_TYPE_SET_GPIO, &pPacket);
00300     packetWriteData(pPacket, 4);
00301     packetWriteData(pPacket, 0);
00302     packetWriteData(pPacket, 8);
00303     cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00304 
00305     /* Check that worked OK */
00306     if (packetGetClass(pReplyPacket) != PACKET_CLASS_NORMAL_RESPONSE) {
00307         /* Abort detection - assume not present */
00308     }
00309 
00310     /* Dispose */
00311     packetDispose(&pPacket);
00312     packetDispose(&pReplyPacket);
00313 
00314     /* Read GPIO[4] */
00315     packetCreate(PACKET_TYPE_GET_GPIO, &pPacket);
00316     packetWriteData(pPacket, 4); /* GPIO 4 */
00317     cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00318 
00319     /* Check that worked OK */
00320     if (packetGetClass(pReplyPacket) != PACKET_CLASS_NORMAL_RESPONSE) {
00321         /* Abort detection - assume not present */
00322     }
00323 
00324     /* Read data */
00325     packetReadData(pReplyPacket, &gpio);
00326     packetReadData(pReplyPacket, &state);
00327 
00328     if (gpio == 4 && state > 0) {
00329         /* SCAB detected */
00330         pInst->bSCABPresent = 1;
00331     }
00332 
00333     /* Dispose */
00334     packetDispose(&pPacket);
00335     packetDispose(&pReplyPacket);
00336 
00337     /* Restore GPIO function to normal */
00338     packetCreate(PACKET_TYPE_SET_GPIO, &pPacket);
00339     packetWriteData(pPacket, 4);
00340     packetWriteData(pPacket, 0);
00341     packetWriteData(pPacket, 7);
00342     cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00343 
00344     /* Dispose */
00345     packetDispose(&pPacket);
00346     packetDispose(&pReplyPacket);
00347 
00348     return (rc);
00349 }
00350 
00351 
00352 int driver_Dispose(LP_DRIVER_INSTANCE * ppDriverInstData)
00353 {
00354     int rc = 0;
00355     
00356     LP_CFONTZ_DEV_INSTANCE * ppInst = (LP_CFONTZ_DEV_INSTANCE *) ppDriverInstData;
00357     LP_CFONTZ_DEV_INSTANCE   pInst  = NULL;
00358     void * pTermValue = NULL;
00359 
00360     if (ppInst == NULL || *ppInst == NULL) {
00361         rc = ERR_BAD_PARAMETER;
00362         goto end_of_function;
00363     }
00364 
00365     /* Convenience */
00366     pInst = *ppInst;
00367 
00368     /* Switch off key reporting */
00369     pInst->keyPressMask   = 0;
00370     pInst->keyReleaseMask = 0;
00371     cfontz_UpdateKeyReport(pInst);
00372 
00373     /* Switch off temperature reporting */
00374     pInst->tempReportMask = 0;
00375     cfontz_UpdateTempReport(pInst);
00376 
00377     /* Switch off fan reporting */
00378     pInst->fanReportMask = 0;
00379     cfontz_UpdateFanReport(pInst);
00380 
00381     /* Stop the receive thread running */
00382     pInst->RxRunning = 0;
00383     
00384     /* Wait for the thread to terminate */
00385     pthread_join(pInst->RxThreadID, &pTermValue);
00386 
00387     /* Shutdown the physical device */
00388 #if defined(_WIN32)
00389     CloseHandle(pInst->Device);
00390 #else
00391     close(pInst->Device);
00392 #endif
00393 
00394     /* Release all memory */
00395 
00396 
00397     if (pInst->pszPort != NULL) {
00398         free(pInst->pszPort);
00399     }
00400 
00401     free(pInst);
00402 
00403 end_of_function:
00404 
00405     return rc;
00406 }
00407 
00408 
00409 int driver_Start(LP_DRIVER_INSTANCE pDriverInstData)
00410 {
00411     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00412 
00413     pInst->bStarted = 1;
00414 
00415     return 0;
00416 }
00417 
00418 
00419 int driver_Stop(LP_DRIVER_INSTANCE pDriverInstData)
00420 {
00421     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00422 
00423     pInst->bStarted = 0;
00424 
00425     return 0;
00426 }
00427 
00428 
00429 int driver_GetScreenSize(LP_DRIVER_INSTANCE pDriverInstData,
00430                          unsigned int * pnScreenWidth, unsigned int * pnScreenHeight)
00431 {
00432     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00433 
00434     *pnScreenHeight = pInst->nHeight;
00435     *pnScreenWidth  = pInst->nWidth;
00436 
00437     return 0;
00438 }
00439 
00440 
00441 int driver_SetLED(LP_DRIVER_INSTANCE pDriverInstData, unsigned int led_id,
00442                   unsigned int nRed, unsigned int nGreen, unsigned int nBlue)
00443 {
00444     int rc = 0;
00445     LPPACKET pPacket = NULL;
00446     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00447 
00448     IILC_TRACE_ENTRY(IILC_MODULE, T_displaySetLED);
00449     traceDebug(IILC_TRACE_CONTEXT,
00450         "pInst %p, led_id %u, nRed %u, nGreen %u, nBlue %u",
00451         pInst, led_id, nRed, nGreen, nBlue);
00452 
00453     /* Ignore the blue content of the colour */
00454 
00455     /* Write out the green component */
00456     packetCreate(PACKET_TYPE_SET_GPIO, &pPacket);
00457     packetWriteData(pPacket, 11 - (led_id * 2));
00458     packetWriteData(pPacket, (unsigned char) nGreen);
00459     cfontz_WritePacket(pInst, pPacket, NULL);
00460     packetDispose(&pPacket);
00461 
00462     /* Write out the red component */
00463     packetCreate(PACKET_TYPE_SET_GPIO, &pPacket);
00464     packetWriteData(pPacket, 12 - (led_id * 2));
00465     packetWriteData(pPacket, (unsigned char) nRed);
00466     cfontz_WritePacket(pInst, pPacket, NULL);
00467     packetDispose(&pPacket);
00468 
00469     IILC_TRACE_EXIT_RC(rc);
00470     return (rc);
00471 }
00472 
00473 
00474 int driver_SetFanFailsafeTimeout(LP_DRIVER_INSTANCE pDriverInstData, unsigned int mask, int milliseconds)
00475 {
00476     int rc = 0, timeout = 0;
00477     PACKET_TYPE replyType = 0;
00478     LPPACKET pPacket = NULL, pReplyPacket = NULL;
00479     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00480 
00481     /* Calculate how many 1/8 second are in 'milliseconds' (1/8s == 125ms) */
00482     timeout = milliseconds / 125;
00483 
00484     /* Ensure we pass a good value in */
00485     if (timeout == 0)       { timeout++; }
00486     else if (timeout > 255) { timeout = 255; }
00487 
00488     rc = packetCreate(PACKET_TYPE_SET_FAN_FAILSAFE, &pPacket);
00489     if (rc) { goto end_of_function; }
00490     
00491     rc = packetWriteData(pPacket, mask);
00492     if (rc) { goto end_of_function; }
00493 
00494     rc = packetWriteData(pPacket, timeout);
00495     if (rc) { goto end_of_function; }
00496 
00497     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00498     if (rc) { goto end_of_function; }
00499 
00500     rc = packetGetType(pReplyPacket, &replyType);
00501     if (replyType != (PACKET_TYPE_SET_FAN_FAILSAFE | 0x40)) {
00502         printf("Bad packet ack received for temperature reporting (%d)\n", replyType);
00503         rc = -1;
00504     }
00505 
00506 end_of_function:
00507 
00508     /* Clean up resources */
00509     if (pPacket != NULL) {
00510         (void) packetDispose(&pPacket);
00511     }
00512 
00513     if (pReplyPacket != NULL) {
00514         (void) packetDispose(&pReplyPacket);
00515     }
00516 
00517     return rc;
00518 }
00519 
00520 
00521 
00522 
00523 /****************************************************************************/
00524 /*                                                                          */
00525 /* Internal functions used to perform various internal operations specific  */
00526 /* to this particular driver.                                               */
00527 /*                                                                          */
00528 /****************************************************************************/
00529 
00530 
00531 
00532 
00533 int cfontz_WritePacket(LP_CFONTZ_DEV_INSTANCE pDevice, LPPACKET pPacket, LPPACKET * ppReplyPacket)
00534 {
00535     int rc = 0;
00536     int run, ret;
00537 
00538     struct timespec timeToWait;
00539 
00540     unsigned char buf[1024];
00541     int bufLen = sizeof(buf) / sizeof(buf[0]);
00542     int dataLen = bufLen;
00543 
00544     LPPACKET pReplyPacket = NULL;
00545 
00546     IILC_TRACE_ENTRY(IILC_MODULE, T_deviceWritePacket);
00547     traceDebug(IILC_TRACE_CONTEXT,
00548         "pDevice %p, pPacket %p, ppReplyPacket %p", pDevice, pPacket, ppReplyPacket);
00549 
00550     IILC_ASSERT(pDevice != NULL);
00551     IILC_ASSERT(pPacket != NULL);
00552 
00553 
00554     /* Flatten the packet into a buffer */
00555     rc = packetFlatten(pPacket, buf, &dataLen);
00556     if (rc) {
00557         traceDebug(IILC_TRACE_CONTEXT, "Failure while flattening packet %d", rc);
00558         goto end_of_function;
00559     }
00560 
00561 
00562     /* ----- Send it to the device ----- */
00563 
00564     /* Repeat this operation a few times */
00565     for (run = 0; run < 10; run++) {
00566 
00567 #if defined(_WIN32)
00568         rc = WriteFile(pDevice->Device, buf, dataLen, &ret, NULL);
00569         if (!rc) {
00570             printf("WriteFile failed\n");
00571         }
00572 #else
00573         ret = write(pDevice->Device, buf, dataLen);
00574 #endif
00575 
00576         if (ret < 0) {
00577             traceDebug(IILC_TRACE_CONTEXT, "write %d %s", ret, strerror(errno));
00578         }
00579         else {
00580             break;
00581         }
00582         if (run > 0) {
00583             traceDebug(IILC_TRACE_CONTEXT, "write(): EAGAIN #%d", run);
00584         }
00585 
00586         SLEEP(1);
00587     }
00588     
00589     if (ret < 0) {
00590         traceDebug(IILC_TRACE_CONTEXT, "write() failed; %s", strerror(errno));
00591         goto end_of_function;
00592     }
00593     else if (ret != dataLen) {
00594         traceDebug(IILC_TRACE_CONTEXT, "partial write(): len=%d ret=%d", dataLen, ret);
00595         goto end_of_function;
00596     }
00597 
00598 
00599     /* ----- Now wait for a response packet ----- */
00600 
00601 
00602     /* Lock the mutex */
00603     rc = pthread_mutex_lock(&pDevice->RxMutex);
00604     if (rc) {
00605         printf("Rx mutex lock failed: %s\n", strerror(errno));
00606         goto end_of_function;
00607     }
00608 
00609     /* Wait for a maximum of 250ms (which is what the PDF user doc says) */
00610     {
00611         unsigned int milliseconds = 250;
00612 
00613         clock_gettime(CLOCK_REALTIME, &timeToWait);
00614 
00615         timeToWait.tv_nsec += (milliseconds % 1000) * 1000000;
00616         timeToWait.tv_sec  += (milliseconds / 1000);
00617 
00618         /* Check within range */
00619         if (timeToWait.tv_nsec > 1000000000) {
00620             timeToWait.tv_sec++;
00621             timeToWait.tv_nsec -= 1000000000;
00622         }
00623     }
00624 
00625     /* Wait on the semaphore */
00626     rc = pthread_cond_timedwait(&(pDevice->RxSemaphore), &(pDevice->RxMutex), &timeToWait);
00627 
00628     if (pDevice->pReplyPacket == NULL) {
00629         printf("No reply packet! rc = %d\n", rc);
00630         exit(1);
00631     }
00632 
00633     if (rc == ETIMEDOUT) {
00634         /* Create a time-out packet for the user */
00635         packetCreate(0xFF, &(pDevice->pReplyPacket));
00636     }
00637     else if (rc) {
00638         printf("Wait on semaphore failed: %s\n", strerror(errno));
00639         goto end_of_function;
00640     }
00641 
00642     /* Grab the returned packet and clear */
00643     pReplyPacket = pDevice->pReplyPacket;
00644     pDevice->pReplyPacket = NULL;
00645 
00646     /* Release the Rx mutex */
00647     rc = pthread_mutex_unlock(&(pDevice->RxMutex));
00648     if (rc) {
00649         printf("Rx mutex unlock failed: %s\n", strerror(errno));
00650         goto end_of_function;
00651     }
00652 
00653 
00654     /* Return packet to the user? */
00655     if (pReplyPacket != NULL) {
00656         /* Does the user wish to know about the returned packet? */
00657         if (ppReplyPacket != NULL) {
00658             *ppReplyPacket = pReplyPacket;
00659         }
00660         else {
00661             packetDispose(&pReplyPacket);
00662         }
00663     }
00664     
00665 end_of_function:
00666 
00667     IILC_TRACE_EXIT_RC(rc);
00668     return rc;
00669 }
00670 
00671 
00672 /*
00673  * Continuously-running thread which handles comms coming from the device.
00674  * Dispatches the received packets either back to the calling thread, or
00675  * to handlers of async events.
00676  */
00677 void * RxThread(void * arg)
00678 {
00679     LP_CFONTZ_DEV_INSTANCE pDevice = (LP_CFONTZ_DEV_INSTANCE) arg;
00680 
00681     int bytesRead = 0;
00682     int bytesAvail = 0;
00683     int ret;
00684 
00685     unsigned char buf[1024];
00686     int bufLen = sizeof(buf) / sizeof(buf[0]);
00687 
00688     do {
00689         int rc = 0;
00690         LPPACKET pReplyPacket = NULL;
00691 
00692         /* Read from the port */
00693 #if defined(_WIN32)
00694         rc = ReadFile(pDevice->Device, &buf[bytesAvail], bufLen - bytesAvail, &ret, NULL);
00695         if (!rc) {
00696             printf("ReadFile failed\n");
00697         }
00698 #else
00699         ret = read(pDevice->Device, &buf[bytesAvail], bufLen - bytesAvail);
00700 #endif
00701 
00702         if (ret < 0 && errno == EAGAIN) {
00703             /* Snooze for 10ms while we wait for something to turn up */
00704             SLEEP(10);
00705             continue;
00706         }
00707 
00708         /* We now have more in the buffer */
00709         bytesAvail += ret;
00710 
00711         /* Nothing has been read from the buffer yet */
00712         bytesRead = 0;
00713 
00714         do {
00715 
00716             /* Attempt to create a packet from bytes avaialble in this buffer */
00717             rc = packetInflate(buf, bytesAvail, &bytesRead, &pReplyPacket);
00718 
00719             /* Remove any bytes that have been read */
00720             if (bytesRead > 0) {
00721                 bytesAvail -= bytesRead;
00722                 memmove(buf, buf + bytesRead, bytesAvail);
00723             }
00724 
00725             /* Have we succeeded? */
00726             if (rc == 0) {
00727 
00728                 /* What sort of packet is this? */
00729                 int packetClass = packetGetClass(pReplyPacket);
00730                 switch (packetClass) {
00731 
00732                 /* Async report from device to app */
00733                 case PACKET_CLASS_NORMAL_REPORT:
00734                 {
00735                     /* Get the packet type */
00736                     PACKET_TYPE packetType;
00737                     packetGetType(pReplyPacket, &packetType);
00738 
00739                     /* Ensure we've been started */
00740                     if (pDevice->bStarted) {
00741 
00742                         /* Decide what to do with this */
00743                         switch (packetType) {
00744 
00745                         case PACKET_TYPE_RPT_TEMP_SENSOR:
00746                             cfontz_ReceiveTempReport(pDevice, pReplyPacket);
00747                             break;
00748 
00749                         case PACKET_TYPE_RPT_FAN_SPEED:
00750                             cfontz_ReceiveFanSpeedReport(pDevice, pReplyPacket);
00751                             break;
00752 
00753                         case PACKET_TYPE_RPT_KEY_ACTIVITY:
00754                             cfontz_ReceiveKeyPressReport(pDevice, pReplyPacket);
00755                             break;
00756 
00757                         default:
00758                             printf("Unknown packet type (%X)\n", packetType);
00759                             break;
00760                         }
00761                     }
00762                     break;
00763                 }
00764 
00765                 /* Both normal and error responses to be handed back to waiting caller */
00766                 case PACKET_CLASS_NORMAL_RESPONSE:
00767                 case PACKET_CLASS_ERROR_RESPONSE:
00768                 {
00769                     PACKET_TYPE ptype;
00770                     packetGetType(pReplyPacket, &ptype);
00771 
00772                     /* Lock the Rx mutex */
00773                     rc = pthread_mutex_lock(&pDevice->RxMutex);
00774                     if (rc) {
00775                         printf("Rx mutex lock failed: %s\n", strerror(errno));
00776                         break;
00777                     }
00778 
00779                     /* Set the reply packet (memory now owned by the device) */
00780                     pDevice->pReplyPacket = pReplyPacket;
00781                     pReplyPacket = NULL;
00782 
00783                     /* Signal the Rx semaphore */
00784                     rc = pthread_cond_signal(&(pDevice->RxSemaphore));
00785                     if (rc) {
00786                         printf("Rx semaphore signal failed: %s\n", strerror(errno));
00787                         break;
00788                     }
00789 
00790                     /* Release the Rx mutex */
00791                     rc = pthread_mutex_unlock(&(pDevice->RxMutex));
00792                     if (rc) {
00793                         printf("Rx mutex unlock failed: %s\n", strerror(errno));
00794                         break;
00795                     }
00796 
00797                     break;
00798                 }
00799 
00800                 /* Shouldn't get this packet received! */
00801                 case PACKET_CLASS_NORMAL_REQUEST:
00802                     printf("Strange packet type received\n");
00803                     break;
00804 
00805                 /* Broken!! */
00806                 default:
00807                     printf("Unable to determine packet class\n");
00808                     break;
00809                 }
00810 
00811                 /* Dispose of the packet */
00812                 if (pReplyPacket != NULL) {
00813                     packetDispose(&pReplyPacket);
00814                 }
00815             }
00816             else if (rc == ERR_INSUFFICIENT_DATA) {
00817                 /* Just a question of waiting for more? */
00818                 SLEEP(10);
00819                 break; /* out of bytesAvail loop */
00820             }
00821             else {
00822                 /* Must be bad */
00823                 printf("Fatal error from packet inflate %d\n", rc);
00824                 break;
00825             }
00826 
00827         } while (bytesAvail > 0);
00828 
00829     } while (pDevice->RxRunning);
00830     
00831     return NULL;
00832 }
00833 
00834 int driver_SetBacklight(LP_DRIVER_INSTANCE pDriverInstData, unsigned int backlightValue)
00835 {
00836     int rc = 0;
00837     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00838     LPPACKET pPacket = NULL, pReplyPacket = NULL;
00839 
00840     rc = packetCreate(PACKET_TYPE_SET_BACKLIGHT, &pPacket);
00841     if (rc) { goto end_of_function; }
00842     
00843     rc = packetWriteData(pPacket, backlightValue);
00844     if (rc) { goto end_of_function; }
00845 
00846     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00847     if (rc) { goto end_of_function; }
00848 
00849 end_of_function:
00850 
00851     if (pPacket != NULL) {
00852         (void) packetDispose(&pPacket);
00853     }
00854     if (pReplyPacket != NULL) {
00855         (void) packetDispose(&pReplyPacket);
00856     }
00857 
00858     return rc;
00859 }
00860 
00861 int driver_SetContrast(LP_DRIVER_INSTANCE pDriverInstData, unsigned int contrastValue)
00862 {
00863     int      rc      = 0;
00864     LPPACKET pPacket = NULL;
00865     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00866 
00867     rc = packetCreate(PACKET_TYPE_SET_LCD_CONTRAST, &pPacket);
00868     if (rc) { goto end_of_function; }
00869     
00870     rc = packetWriteData(pPacket, contrastValue);
00871     if (rc) { goto end_of_function; }
00872 
00873     rc = cfontz_WritePacket(pInst, pPacket, NULL);
00874     if (rc) { goto end_of_function; }
00875 
00876 end_of_function:
00877 
00878     if (pPacket != NULL) { packetDispose(&pPacket); }
00879 
00880     return rc;
00881 }
00882 
00883 
00884 int driver_ClearScreen(LP_DRIVER_INSTANCE pDriverInstData)
00885 {
00886     int rc = 0;
00887     LPPACKET pPacket = NULL;
00888     LPPACKET pReplyPacket = NULL;
00889     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00890 
00891     rc = packetCreate(PACKET_TYPE_CLEAR_SCREEN, &pPacket);
00892     if (rc) { goto end_of_function; }
00893     
00894     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00895     if (rc) { goto end_of_function; }
00896 
00897 end_of_function:
00898 
00899     if (pPacket != NULL) { packetDispose(&pPacket); }
00900     if (pReplyPacket != NULL) { packetDispose(&pReplyPacket); }
00901 
00902     return rc;
00903 }
00904 
00905 
00906 
00907 int driver_WriteText(LP_DRIVER_INSTANCE pDriverInstData, unsigned int x, unsigned int y, char * strData, unsigned int width)
00908 {
00909     int rc = 0;
00910     LPPACKET pPacket = NULL, pReplyPacket = NULL;
00911     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00912 
00913     rc = packetCreate(PACKET_TYPE_WRITE_DATA, &pPacket);
00914     if (rc) { goto end_of_function; }
00915     
00916     rc = packetWriteData(pPacket, x);
00917     if (rc) { goto end_of_function; }
00918 
00919     rc = packetWriteData(pPacket, y);
00920     if (rc) { goto end_of_function; }
00921 
00922     rc = packetWriteString(pPacket, strData, width);
00923     if (rc) { goto end_of_function; }
00924 
00925     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
00926     if (rc) { goto end_of_function; }
00927 
00928 end_of_function:
00929 
00930     if (pPacket)      { packetDispose(&pPacket); }
00931     if (pReplyPacket) { packetDispose(&pReplyPacket); }
00932 
00933     return rc;
00934 }
00935 
00936 
00937 
00938 int driver_Restart(LP_DRIVER_INSTANCE pDriverInstData)
00939 {
00940     int rc = 0;
00941     LPPACKET pPacket = NULL;
00942     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00943 
00944     rc = packetCreate(PACKET_TYPE_POWER_CONTROL, &pPacket);
00945     if (rc) { goto end_of_function; }
00946     
00947     rc = packetWriteData(pPacket, 8);
00948     if (rc) { goto end_of_function; }
00949 
00950     rc = packetWriteData(pPacket, 18);
00951     if (rc) { goto end_of_function; }
00952 
00953     rc = packetWriteData(pPacket, 99);
00954     if (rc) { goto end_of_function; }
00955 
00956     rc = cfontz_WritePacket(pInst, pPacket, NULL);
00957     if (rc) { goto end_of_function; }
00958 
00959 end_of_function:
00960 
00961     /* Clean up resources */
00962     if (pPacket != NULL) {
00963         (void) packetDispose(&pPacket);
00964     }
00965 
00966     return rc;
00967 }
00968 
00969 int driver_SetFanPower(LP_DRIVER_INSTANCE pDriverInstData, unsigned int fan_id, unsigned int nPower)
00970 {
00971     int rc = 0;
00972 
00973     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
00974 
00975     IILC_TRACE_ENTRY(IILC_MODULE, T_driver_SetFanPower);
00976     traceDebug(IILC_TRACE_CONTEXT, "pInst %p, fan_id %u, nPower %u", pInst, fan_id, nPower);
00977 
00978     /* Sanity check */
00979     if (pDriverInstData == NULL) {
00980         rc = ERR_BAD_PARAMETER;
00981         goto end_of_function;
00982     }
00983 
00984     /* Fans numbered from 0 */
00985     if (fan_id >= pInst->nFanCount) {
00986         rc = ERR_BAD_PARAMETER;
00987         goto end_of_function;
00988     }
00989 
00990     /* Should be a percentage */
00991     if (nPower > 100) {
00992         rc = ERR_BAD_PARAMETER;
00993         goto end_of_function;
00994     }
00995 
00996     /* Keep track internally */
00997     pInst->nFanPower[fan_id] = nPower;
00998 
00999     /* Update the device */
01000     cfontz_UpdateFanPower(pInst);
01001 
01002 end_of_function:
01003 
01004     IILC_TRACE_EXIT_RC(rc);
01005     return rc;
01006 }
01007 
01008 int cfontz_UpdateFanReport(LP_CFONTZ_DEV_INSTANCE pInst)
01009 {
01010     int rc = 0;
01011     LPPACKET pPacket = NULL;
01012     LPPACKET pReplyPacket = NULL;
01013 
01014     /* Send to the display */
01015     rc = packetCreate(PACKET_TYPE_SET_FAN_REPORTING, &pPacket);
01016     if (rc) { goto end_of_function; }
01017     
01018     rc = packetWriteData(pPacket, pInst->fanReportMask);
01019     if (rc) { goto end_of_function; }
01020 
01021     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
01022     if (rc) { goto end_of_function; }
01023 
01024 end_of_function:
01025 
01026     if (pPacket) packetDispose(&pPacket);
01027     if (pReplyPacket) packetDispose(&pReplyPacket);
01028 
01029     return rc;
01030 }
01031 
01032 
01033 int cfontz_UpdateKeyReport(LP_CFONTZ_DEV_INSTANCE pInst)
01034 {
01035     int rc = 0;
01036     LPPACKET pPacket = NULL;
01037     LPPACKET pReplyPacket = NULL;
01038 
01039     /* Send to the display */
01040     rc = packetCreate(PACKET_TYPE_SET_KEY_REPORTING, &pPacket);
01041     if (rc) { goto end_of_function; }
01042     
01043     rc = packetWriteData(pPacket, pInst->keyPressMask);
01044     if (rc) { goto end_of_function; }
01045 
01046     rc = packetWriteData(pPacket, pInst->keyReleaseMask);
01047     if (rc) { goto end_of_function; }
01048 
01049     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
01050     if (rc) { goto end_of_function; }
01051 
01052 end_of_function:
01053 
01054     if (pPacket) packetDispose(&pPacket);
01055     if (pReplyPacket) packetDispose(&pReplyPacket);
01056 
01057     return rc;
01058 }
01059 
01060 int driver_EnableFanReport(LP_DRIVER_INSTANCE pDriverInstData, unsigned int fan_id)
01061 {
01062     int rc = 0;
01063 
01064     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
01065 
01066     /* Setup the mask & update */
01067     pInst->fanReportMask |= (1 << fan_id);
01068     rc = cfontz_UpdateFanReport(pInst);
01069 
01070     return rc;
01071 }
01072 
01073 int driver_DisableFanReport(LP_DRIVER_INSTANCE pDriverInstData, unsigned int fan_id)
01074 {
01075     int rc = 0;
01076 
01077     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
01078 
01079     /* Setup the mask & update */
01080     pInst->fanReportMask &= ~(1 << fan_id);
01081     rc = cfontz_UpdateFanReport(pInst);
01082 
01083     return rc;
01084 }
01085 
01086 int driver_EnableTempReport(LP_DRIVER_INSTANCE pDriverInstData, unsigned int sensor_id)
01087 {
01088     int rc = 0;
01089 
01090     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
01091 
01092     /* Setup the mask & update */
01093     pInst->tempReportMask |= (1 << sensor_id);
01094     rc = cfontz_UpdateTempReport(pInst);
01095 
01096     return rc;
01097 }
01098 
01099 int driver_DisableTempReport(LP_DRIVER_INSTANCE pDriverInstData, unsigned int sensor_id)
01100 {
01101     int rc = 0;
01102 
01103     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
01104 
01105     /* Setup the mask & update */
01106     pInst->tempReportMask &= ~(1 << sensor_id);
01107     rc = cfontz_UpdateTempReport(pInst);
01108 
01109     return rc;
01110 }
01111 
01112 
01113 int driver_SetTemperatureReporting(LP_DRIVER_INSTANCE pDriverInstData, unsigned int mask)
01114 {
01115     int rc = 0;
01116     //PACKET_TYPE replyType = 0;
01117     LPPACKET pPacket = NULL, pReplyPacket = NULL;
01118     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
01119 
01120     rc = packetCreate(PACKET_TYPE_SET_TEMP_REPORTING, &pPacket);
01121     if (rc) { goto end_of_function; }
01122     
01123     rc = packetWriteData(pPacket, mask & 0x000000FF);
01124     if (rc) { goto end_of_function; }
01125 
01126     rc = packetWriteData(pPacket, (mask & 0x0000FF00) >> 8);
01127     if (rc) { goto end_of_function; }
01128 
01129     rc = packetWriteData(pPacket, (mask & 0x00FF0000) >> 16);
01130     if (rc) { goto end_of_function; }
01131 
01132     rc = packetWriteData(pPacket, (mask & 0xFF000000) >> 24);
01133     if (rc) { goto end_of_function; }
01134 
01135     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
01136     if (rc) { goto end_of_function; }
01137 
01138     /*
01139     rc = packetGetType(pReplyPacket, &replyType);
01140     if (replyType != (PACKET_TYPE_SET_TEMP_REPORTING | 0x40)) {
01141         printf("Bad packet ack received for temperature reporting (%d)\n", replyType);
01142         rc = -1;
01143     }
01144     */
01145 
01146 end_of_function:
01147 
01148     /* Clean up resources */
01149     if (pPacket != NULL) {
01150         (void) packetDispose(&pPacket);
01151     }
01152 
01153     if (pReplyPacket != NULL) {
01154         (void) packetDispose(&pReplyPacket);
01155     }
01156 
01157     return rc;
01158 }
01159 
01163 int cfontz_ReceiveFanSpeedReport(LP_CFONTZ_DEV_INSTANCE pInst, LPPACKET pPacket)
01164 {
01165     int rc = 0;
01166 
01167     /* Final fan speed value */
01168     unsigned int fanSpeed = 0;
01169     
01170     /* Raw data from the packet */
01171     unsigned char LSB, MSB, fan_number, number_of_fan_tach_cycles;
01172 
01173     /* Pulses Per Revolution  - specific to each fan, most commonly 2 */
01174     const int PPR = 2;
01175 
01176     /* Join of MSB+LSB */
01177     unsigned short Fan_Timer_Ticks;
01178 
01179     IILC_TRACE_ENTRY(IILC_MODULE, T_displayReceiveFanSpeedReport);
01180     traceDebug(IILC_TRACE_CONTEXT, "pInst %p, pPacket %p", pInst, pPacket);
01181 
01182     /* Do we have any listeners? */
01183     if (pInst->pfn.FanSpeed == NULL) {
01184         goto end_of_function;
01185     }
01186 
01187     /* Read the raw data from the packet */
01188     if (!rc) { rc = packetReadData(pPacket, &fan_number); }
01189     if (!rc) { rc = packetReadData(pPacket, &number_of_fan_tach_cycles); }
01190     if (!rc) { rc = packetReadData(pPacket, &LSB); }
01191     if (!rc) { rc = packetReadData(pPacket, &MSB); }
01192     if (rc) {
01193         traceWarning(IILC_TRACE_CONTEXT, "Badly-formed fan speed report packet");
01194         goto end_of_function;
01195     }
01196 
01197     /* Convert raw data to something useful */
01198     Fan_Timer_Ticks = (MSB << 8) + LSB;
01199 
01200     /* Useful information dumped our to trace */
01201     traceDebug(IILC_TRACE_CONTEXT,
01202         "fan_number " T_FMT_UINT " Fan_Timer_Ticks " T_FMT_UINT " Tach_Cycles " T_FMT_UINT,
01203         (unsigned int) fan_number, (unsigned int) Fan_Timer_Ticks, number_of_fan_tach_cycles);
01204 
01205     if (number_of_fan_tach_cycles <= 3) {        
01206         fanSpeed = 0; /* Stopped */
01207     }
01208     else if (number_of_fan_tach_cycles <= 4) {        
01209         fanSpeed = 1; /* Too slow to measure */
01210     }
01211     else if (number_of_fan_tach_cycles == 0xFF) {
01212         fanSpeed = 0XFFFFFFFF; /* Out of range */
01213     }
01214     else {
01215         /* Use the formula provided by CF-635 data sheet v 1.4 */
01216         fanSpeed = ((27692308L / PPR) * (unsigned long)(number_of_fan_tach_cycles - 3)) / (Fan_Timer_Ticks);
01217     }
01218 
01219     traceDebug(IILC_TRACE_CONTEXT, "fan speed " T_FMT_UINT, fanSpeed);
01220 
01221     /* Send this data to the callback */
01222     (pInst->pfn.FanSpeed)(pInst->context.FanSpeed, (unsigned int) fan_number, fanSpeed);
01223 
01224 end_of_function:
01225 
01226     IILC_TRACE_EXIT;
01227     return rc;
01228 }
01229 
01230 
01231 int cfontz_ReceiveKeyPressReport(LP_CFONTZ_DEV_INSTANCE pInst, LPPACKET pPacket)
01232 {
01233     unsigned char event;
01234 
01235     IILC_TRACE_ENTRY(IILC_MODULE, T_displayReceiveKeyPressReport);
01236     traceDebug(IILC_TRACE_CONTEXT, "pInst %p, pPacket %p", pInst, pPacket);
01237 
01238     /* Ignore if no-one is bothered about receiving reports */
01239     if (pInst->pfn.KeyEvent == NULL) {
01240         goto end_of_function;
01241     }
01242 
01243     /* Read the data */
01244     packetReadData(pPacket, &event);
01245 
01246     /* Perform the callback */
01247     (pInst->pfn.KeyEvent)(pInst->context.KeyEvent, 0);
01248 
01249 end_of_function:
01250 
01251     IILC_TRACE_EXIT;
01252     return 0;
01253 }
01254 
01255 
01259 int cfontz_ReceiveTempReport(LP_CFONTZ_DEV_INSTANCE pInst, LPPACKET pPacket)
01260 {
01261     int rc = 0;
01262     //int i = 0;
01263     double degc = 0.0;
01264     unsigned char sensor, MSB, LSB, DOW_crc_status;
01265     unsigned short report;
01266 
01267     IILC_TRACE_ENTRY(IILC_MODULE, T_cfontz_ReceiveTempReport);
01268     traceDebug(IILC_TRACE_CONTEXT, "pInst %p, pPacket %p", pInst, pPacket);
01269 
01270     /* Do we have any callbacks registered? */
01271     if (pInst->pfn.Temp == NULL) {
01272         traceDebug(IILC_TRACE_CONTEXT, "No temp callbacks registered");
01273         goto end_of_function;
01274     }
01275 
01276     /* Read the raw data */
01277     packetReadData(pPacket, &sensor);
01278     packetReadData(pPacket, &LSB);
01279     packetReadData(pPacket, &MSB);
01280     packetReadData(pPacket, &DOW_crc_status);
01281 
01282     /* Check CRC is OK */
01283     if (DOW_crc_status == 0) {
01284         printf("Bad DOW CRC\n");
01285         rc = -1;
01286         goto end_of_function;
01287     }
01288 
01289     /* Convert to a full 16-bit value and get true reading */
01290     report = (MSB << 8) + LSB;
01291     degc = ((double) report) / 16.0; 
01292 
01293     (pInst->pfn.Temp)(pInst->context.Temp, sensor, degc);
01294 
01295 end_of_function:
01296 
01297     IILC_TRACE_EXIT_RC(rc);
01298     return rc;
01299 }
01300 
01301 
01302 
01303 int driver_SetCallbackTemp(LP_DRIVER_INSTANCE pDriverInstData, pfnDrvCBTemp pfn, void * context)
01304 {
01305     int rc = 0;
01306     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
01307 
01308     pInst->pfn.Temp     = pfn;
01309     pInst->context.Temp = context;
01310 
01311     return rc;   
01312 }
01313 
01314 int driver_SetCallbackFan(LP_DRIVER_INSTANCE pDriverInstData, pfnDrvCBFanSpeed pfn, void * context)
01315 {
01316     int rc = 0;
01317     LP_CFONTZ_DEV_INSTANCE pInst = (LP_CFONTZ_DEV_INSTANCE) pDriverInstData;
01318 
01319     pInst->pfn.FanSpeed     = pfn;
01320     pInst->context.FanSpeed = context;
01321 
01322     return rc;
01323 }
01324 
01325 int cfontz_SetCallbackKeyEvent(LP_CFONTZ_DEV_INSTANCE pInst, pfnDrvCBKeyEvent pfn, void * context)
01326 {
01327     pInst->pfn.KeyEvent     = pfn;
01328     pInst->context.KeyEvent = context;
01329     return 0;
01330 }
01331 
01332 
01333 int cfontz_InitDeviceType(LP_CFONTZ_DEV_INSTANCE pInst, const char * pszVersionString)
01334 {
01335     int rc = 0;
01336 
01337     IILC_TRACE_ENTRY(IILC_MODULE, T_cfontz_InitDeviceType);
01338 
01339     if (strncmp(pszVersionString, CFONTZ_CFA635_STRING, strlen(CFONTZ_CFA635_STRING)) == 0) {
01340 
01341         /* CFA-635 */
01342         pInst->deviceType = CFONTZ_DEVICE_TYPE_CFA635;
01343         pInst->nHeight   = 4;
01344         pInst->nWidth    = 20;
01345         pInst->nLEDCount = 4;
01346         pInst->nFanCount = 0;
01347 
01348         /* Do we have a SCAB present? */
01349         rc = cfontz_detectSCAB(pInst);
01350         if (rc) { goto end_of_function; }
01351 
01352         /* Some init can only happen with a SCAB present */
01353         if (pInst->bSCABPresent) {
01354 
01355             /* No way of really knowing for sure how many fans are attached - max 4 though */
01356             pInst->nFanCount = 4; 
01357         }
01358     }
01359     else if (strncmp(pszVersionString, CFONTZ_CFA633_STRING, strlen(CFONTZ_CFA633_STRING)) == 0) {
01360 
01361         /* CFA-633 */
01362         pInst->deviceType = CFONTZ_DEVICE_TYPE_CFA633;
01363         pInst->nHeight   = 2;
01364         pInst->nWidth    = 16;
01365         pInst->nLEDCount = 0;
01366         pInst->nFanCount = 0;
01367     }
01368     else {
01369         traceDebug(IILC_TRACE_CONTEXT, "Did not recognise device type");
01370     }
01371 
01372 end_of_function:
01373 
01374     IILC_TRACE_EXIT_RC(rc);
01375     return rc;
01376 }
01377 
01378 int cfontz_UpdateFanPower(LP_CFONTZ_DEV_INSTANCE pInst)
01379 {
01380     int rc = 0;
01381     int i = 0;
01382 
01383     LPPACKET pPacket = NULL, pReplyPacket = NULL;
01384 
01385     /* Sanity check */
01386     if (pInst == NULL) {
01387         rc = ERR_BAD_PARAMETER;
01388         goto end_of_function;
01389     }
01390 
01391     /* All fans have been set to sensible values already */
01392     rc = packetCreate(PACKET_TYPE_SET_FAN_POWER, &pPacket);
01393     if (rc) { goto end_of_function; }
01394     
01395     /* Write all fan data */
01396     for (i = 0; i < pInst->nFanCount; i++) {
01397         packetWriteData(pPacket, pInst->nFanPower[i]);
01398     }
01399 
01400     /* Send data to the display */
01401     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
01402     if (rc) { goto end_of_function; }
01403 
01404     /*
01405     rc = packetGetType(pReplyPacket, &replyType);
01406     if (replyType != (PACKET_TYPE_SET_TEMP_REPORTING | 0x40)) {
01407         printf("Bad packet ack received for temperature reporting (%d)\n", replyType);
01408         rc = -1;
01409     }
01410     */
01411 
01412 end_of_function:
01413 
01414     /* Clean up resources */
01415     if (pPacket)      { (void) packetDispose(&pPacket); }
01416     if (pReplyPacket) { (void) packetDispose(&pReplyPacket); }
01417 
01418     return rc;
01419 
01420 
01421 }
01422 
01430 int cfontz_UpdateTempReport(LP_CFONTZ_DEV_INSTANCE pInst)
01431 {
01432     int rc = 0;
01433     int i = 0;
01434 
01435     LPPACKET pPacket = NULL, pReplyPacket = NULL;
01436     PACKET_TYPE replyType;
01437 
01438     IILC_TRACE_ENTRY(IILC_MODULE, T_cfontz_UpdateTempReport);
01439 
01440     /* Sanity check */
01441     if (pInst == NULL) {
01442         rc = ERR_BAD_PARAMETER;
01443         goto end_of_function;
01444     }
01445 
01446     /* All fans have been set to sensible values already */
01447     rc = packetCreate(PACKET_TYPE_SET_TEMP_REPORTING, &pPacket);
01448     if (rc) { goto end_of_function; }
01449     
01450     /* Write all fan data */
01451     for (i = 0; i < 4; i++) {
01452         unsigned int val = (pInst->tempReportMask & (0xFF << (i*8))) >> (i*8);
01453         packetWriteData(pPacket, (unsigned char) val);
01454         traceDebug(IILC_TRACE_CONTEXT, "Written data %u", val);
01455     }
01456 
01457     /* Send data to the display */
01458     rc = cfontz_WritePacket(pInst, pPacket, &pReplyPacket);
01459     if (rc) { goto end_of_function; }
01460 
01461     rc = packetGetType(pReplyPacket, &replyType);
01462     if (replyType != (PACKET_TYPE_SET_TEMP_REPORTING | 0x40)) {
01463         traceError(IILC_TRACE_CONTEXT, 
01464             "Bad packet ack received for temperature reporting (%d)\n", replyType);
01465         rc = -1;
01466         goto end_of_function;
01467     }
01468 
01469 end_of_function:
01470 
01471     /* Clean up resources */
01472     if (pPacket)      { (void) packetDispose(&pPacket); }
01473     if (pReplyPacket) { (void) packetDispose(&pReplyPacket); }
01474 
01475     IILC_TRACE_EXIT_RC(rc);
01476     return rc;
01477 
01478 
01479 }

Generated on Mon Jul 17 01:36:11 2006 for IILC by  doxygen 1.4.6