OPENRAPI.cc

Go to the documentation of this file.
00001 /*
00002  * This file is part of openSDK.
00003  *
00004  * Copyright (C) 2006-2007 openSDK team
00005  *
00006  * openSDK 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; version 2.
00009  *
00010  * openSDK is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with openSDK; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  *
00019  *     $Id: OPENRAPI.cc,v 1.24 2007/07/16 15:21:43 nuno-lopes Exp $
00020  */
00021 
00022 #include <OPENR/OPENRAPI.h>
00023 #include <OPENR/OPENRMessages.h>
00024 #include <iostream>
00025 #include <fstream>
00026 #include <map>
00027 #include <cstdlib>
00028 #include <cstring>
00029 #include <cctype>
00030 #include <pthread.h>
00031 #include <boot.h>
00032 #include <utils.h>
00033 #include <Platform.h>
00034 #include <Primitives.h>
00035 #include <MemoryMapAgent.h>
00036 #include <ModuleData.h>
00037 #include <opensdkAPI.h>
00038 
00039 using namespace std;
00040 
00041 #define LOCK(m) pthread_mutex_lock(&m ##_mutex)
00042 #define UNLOCK(m) pthread_mutex_unlock(&m ##_mutex)
00043 
00044 // global variables that control the state of the robot
00045 static longword myRobotStatus = orsbBATTERY_CONNECTED | orsbBATTERY_CAPACITY_FULL;
00046 static word myBatteryStatus = obsbFULLY_CHARGED;
00047 static word myRemainingCapacity = 100; // battery remaining capacity (percentage)
00048 static word myTemperature = 300; // temperature (Kelvins)
00049 static word myFullyChargedCapacity = 55555; // in mAh
00050 static word myVoltage = 5000; // battery voltage (mV)
00051 static word myCurrent = 1000; // battery current (mA)
00052 static OVolumeSwitch myVolume = ovolumeSW3; //volume level
00053 static OPower motorPower = opowerOFF;
00054 static word myBootCondition = 0;
00055 
00056 // list of observers of the power status changes
00057 static map<OServiceEntry, OPowerStatus> powerStatusObservers;
00058 static pthread_mutex_t powerStatusObservers_mutex = PTHREAD_MUTEX_INITIALIZER;
00059 
00060 #define sendPowerStatusNotifications(property, bitmask) \
00061 { \
00062         LOCK(powerStatusObservers); \
00063 \
00064         for(map<OServiceEntry, OPowerStatus>::iterator it = powerStatusObservers.begin(); it != powerStatusObservers.end(); ++it) { \
00065                 if (it->second.property & bitmask) { \
00066                         OPowerStatusMessage *status = new OPowerStatusMessage(myRobotStatus, myBatteryStatus, myRemainingCapacity, myTemperature, myFullyChargedCapacity, myVoltage, myCurrent, ::GetTimeDifference(), myVolume); \
00067                         _sendMessage(it->first, status); \
00068                 } \
00069         } \
00070 \
00071         UNLOCK(powerStatusObservers); \
00072 }
00073 
00074 
00075 OStatus OPENR::OpenPrimitive(const char* locator, OPrimitiveID* primitiveID)
00076 {
00077         // by default, the primitiveID should be set to the constant below
00078         *primitiveID = oprimitiveID_UNDEF;
00079 
00080         if (!locator) {
00081                 return oINVALID_ARG;
00082         }
00083 
00084         //binary search to find the primitive ID
00085         int left = 0, right = num_of_primitives - 1;
00086 
00087         do {
00088                 unsigned int mid = (left + right) / 2;
00089                 int cmp = strcmp(locator, primitives[mid].locator);
00090 
00091                 if (cmp < 0) {
00092                         right = mid - 1;
00093                 } else if (cmp > 0) {
00094                         left = mid + 1;
00095                 } else {
00096                         //TODO: mark the primitive as open
00097                         *primitiveID = mid;
00098                         return oSUCCESS;
00099                 }
00100         } while(left <= right);
00101 
00102         return oNOT_FOUND;
00103 }
00104 
00105 OStatus OPENR::ClosePrimitive(OPrimitiveID primitiveID)
00106 {
00107         CHECK_PRIMITIVEID()
00108         //TODO
00109         return oSUCCESS;
00110 }
00111 
00112 OStatus OPENR::ControlPrimitive(OPrimitiveID primitiveID, OPrimitiveRequest request, void* param, size_t paramSize, void* result, size_t resultSize)
00113 {
00114         CHECK_PRIMITIVEID()
00115 
00116         switch (request) {
00117 
00118 
00119 
00120                 default:
00121                         return oINVALID_ARG;
00122         }
00123 }
00124 
00125 OStatus OPENR::NewCommandVectorData(size_t numCommands, MemoryRegionID* memID, OCommandVectorData** baseAddr)
00126 {
00127         const size_t size = sizeof(OCommandVectorData) + (sizeof(OCommandInfo) + sizeof(OCommandData))*numCommands;
00128         OCommandVectorData *data = *baseAddr = (OCommandVectorData*)malloc(size);
00129 
00130         if (!data) {
00131                 return oNO_MEMORY;
00132         }
00133 
00134         data->vectorInfo.memRegionID = *memID = RegisterNewMemID(data);
00135         data->SetNumData(0);
00136         data->vectorInfo.offset = 0;
00137         data->vectorInfo.totalSize = size;
00138 
00139         for (size_t i=0; i < numCommands; ++i) {
00140                 OCommandInfo *info = data->GetInfo(i);
00141                 info->dataOffset = sizeof(ODataVectorInfo) + sizeof(OCommandInfo)*numCommands + sizeof(OCommandData)*i;
00142         }
00143 
00144         return oSUCCESS;
00145 }
00146 
00147 OStatus OPENR::DeleteCommandVectorData(MemoryRegionID memID)
00148 {
00149         return FreeMemId(memID);
00150 }
00151 
00152 OStatus OPENR::NewSoundVectorData(size_t numSounds, size_t dataSize, MemoryRegionID* memID, OSoundVectorData** baseAddr)
00153 {
00154         const size_t size = sizeof(OSoundVectorData) + (sizeof(OSoundInfo) + dataSize)*numSounds;
00155         OSoundVectorData *data = *baseAddr = (OSoundVectorData*)malloc(size);
00156 
00157         if (!data) {
00158                 return oNO_MEMORY;
00159         }
00160 
00161         data->vectorInfo.memRegionID = *memID = RegisterNewMemID(data);
00162         data->SetNumData(0);
00163         data->vectorInfo.offset = 0;
00164         data->vectorInfo.totalSize = size;
00165 
00166         for (size_t i=0; i < numSounds; ++i) {
00167                 OSoundInfo *info = data->GetInfo(i);
00168                 info->dataOffset = sizeof(ODataVectorInfo) + sizeof(OSoundInfo)*numSounds + dataSize*i;
00169         }
00170 
00171         return oSUCCESS;
00172 }
00173 
00174 OStatus OPENR::DeleteSoundVectorData(MemoryRegionID memID)
00175 {
00176         return FreeMemId(memID);
00177 }
00178 
00179 OStatus OPENR::EnableJointGain(OPrimitiveID primitiveID)
00180 {
00181         CHECK_PRIMITIVEID_ALL()
00182         //TODO
00183         return oSUCCESS;
00184 }
00185 
00186 OStatus OPENR::DisableJointGain(OPrimitiveID primitiveID)
00187 {
00188         CHECK_PRIMITIVEID_ALL()
00189         //TODO
00190         return oSUCCESS;
00191 }
00192 
00193 OStatus OPENR::SetJointGain(OPrimitiveID primitiveID, word pg, word ig, word dg, word ps, word is, word ds)
00194 {
00195         CHECK_PRIMITIVEID_ALL()
00196         //TODO
00197         return oSUCCESS;
00198 }
00199 
00200 OStatus OPENR::RegisterDefaultJointGain(OPrimitiveID primitiveID, word pg, word ig, word dg, word ps, word is, word ds)
00201 {
00202         CHECK_PRIMITIVEID_ALL()
00203 
00204         if (primitiveID == oprimitiveID_UNDEF) {
00205                 //TODO
00206         }
00207 
00208         primitives[primitiveID].pg = pg;
00209         primitives[primitiveID].ig = ig;
00210         primitives[primitiveID].dg = dg;
00211         primitives[primitiveID].ps = ps;
00212         primitives[primitiveID].is = is;
00213         primitives[primitiveID].ds = ds;
00214 
00215         return oSUCCESS;
00216 }
00217 
00218 OStatus OPENR::GetJointGain(OPrimitiveID primitiveID, word* pg, word* ig, word* dg, word* ps, word* is, word* ds)
00219 {
00220         CHECK_PRIMITIVEID()
00221         //TODO
00222         return oFAIL;
00223 }
00224 
00225 OStatus OPENR::GetDefaultJointGain(OPrimitiveID primitiveID, word* pg, word* ig, word* dg, word* ps, word* is, word* ds)
00226 {
00227         if (primitiveID >= num_of_primitives || primitiveID < 0) {
00228                 *pg = *ig = *dg = *ps = *is = *ds = 0;
00229                 return oFAIL;
00230         }
00231 
00232         *pg = primitives[primitiveID].pg;
00233         *ig = primitives[primitiveID].ig;
00234         *dg = primitives[primitiveID].dg;
00235         *ps = primitives[primitiveID].ps;
00236         *is = primitives[primitiveID].is;
00237         *ds = primitives[primitiveID].ds;
00238 
00239         return oSUCCESS;
00240 }
00241 
00242 OStatus OPENR::SetDefaultJointGain(OPrimitiveID primitiveID)
00243 {
00244         CHECK_PRIMITIVEID_ALL()
00245         //TODO
00246         return oFAIL;
00247 }
00248 
00249 OStatus OPENR::GetJointValue(OPrimitiveID primitiveID, OJointValue* value)
00250 {
00251         CHECK_PRIMITIVEID()
00252         return ::GetJointValue(primitiveID, value);
00253 }
00254 
00255 OStatus OPENR::GetSensorValue(OPrimitiveID primitiveID, OSensorValue* value)
00256 {
00257         CHECK_PRIMITIVEID()
00258         return ::GetSensorValue(primitiveID, value);
00259 }
00260 
00261 OStatus OPENR::NewSyncKey(OVRSyncKey* key)
00262 {
00263         //TODO
00264         return oFAIL;
00265 }
00266 
00267 OStatus OPENR::CancelSyncKey(OVRSyncKey key)
00268 {
00269         //TODO
00270         return oFAIL;
00271 }
00272 
00273 OStatus OPENR::DivideSyncKey(OVRSyncKey key, OVRSyncKey* key1, OVRSyncKey* key2)
00274 {
00275         //TODO
00276         return oFAIL;
00277 }
00278 
00279 OStatus OPENR::NewCdtVectorData(MemoryRegionID* memID, OCdtVectorData** baseAddr)
00280 {
00281         OCdtVectorData *data = *baseAddr = (OCdtVectorData*)malloc(sizeof(OCdtVectorData));
00282         data->vectorInfo.memRegionID = *memID = RegisterNewMemID(data);
00283         data->SetNumData(0);
00284         data->vectorInfo.offset = 0;
00285         data->vectorInfo.totalSize = sizeof(OCdtVectorData);
00286 
00287         return oSUCCESS;
00288 }
00289 
00290 OStatus OPENR::DeleteCdtVectorData(MemoryRegionID memID)
00291 {
00292         return FreeMemId(memID);
00293 }
00294 
00295 OStatus OPENR::SetCdtVectorData(MemoryRegionID memID)
00296 {
00297         //TODO
00298         return oFAIL;
00299 }
00300 
00301 OStatus OPENR::SetMotorPower(OPower power)
00302 {
00303         bool changed = false;
00304         motorPower = power;
00305 
00306         if (power) {
00307                 if (!(power & orsbMOTOR_POWER)) {
00308                         myRobotStatus |= orsbMOTOR_POWER;
00309                         changed = true;
00310                 }
00311         } else {
00312                 if (power & orsbMOTOR_POWER) {
00313                         myRobotStatus &= ~orsbMOTOR_POWER;
00314                         changed = true;
00315                 }
00316         }
00317 
00318         if (changed) {
00319                 sendPowerStatusNotifications(robotStatus, orsbMOTOR_POWER);
00320         }
00321 
00322         return oSUCCESS;
00323 }
00324 
00325 OStatus OPENR::Shutdown(const OBootCondition& bootCondition)
00326 {
00327         //TODO: finish these if's
00328         if (bootCondition.bitmap & obcbPAUSE_SW) {
00329                 myBootCondition |= obcbPAUSE_SW;
00330                 myRobotStatus   |= orsbPAUSE;
00331 
00332                 sendPowerStatusNotifications(robotStatus, orsbPAUSE);
00333                 shutdown();
00334                 return oSUCCESS;
00335         } /*else if (bootCondition.bitmap & obcbBOOT_TIMER) {
00336                 if (set_shutdown_timer(bootCondition.bootTime, bootCondition.bootTimeType) == oSUCCESS) {
00337                         return oSUCCESS;
00338                 }
00339         } */
00340 
00341         return oFAIL;
00342 }
00343 
00344 OStatus OPENR::GetBootCondition(OBootCondition* bootCondition)
00345 {
00346         bootCondition->bitmap = myBootCondition;
00347         return oSUCCESS;
00348 }
00349 
00350 OStatus OPENR::GetPowerStatus(OPowerStatus* powerStatus)
00351 {
00352         powerStatus->robotStatus = myRobotStatus;
00353         powerStatus->batteryStatus = myBatteryStatus;
00354         powerStatus->remainingCapacity = myRemainingCapacity;
00355         powerStatus->temperature = myTemperature;
00356         powerStatus->fullyChargedCapacity = myFullyChargedCapacity;
00357         powerStatus->voltage = myVoltage;
00358         powerStatus->current = myCurrent;
00359         powerStatus->timeDif = ::GetTimeDifference();
00360         powerStatus->volume = myVolume;
00361         return oSUCCESS;
00362 }
00363 
00364 OStatus OPENR::ObservePowerStatus(const OPowerStatus& notifyStatus, const OServiceEntry& entry)
00365 {
00366         LOCK(powerStatusObservers);
00367         powerStatusObservers[entry] = notifyStatus;
00368         UNLOCK(powerStatusObservers);
00369 
00370         return oSUCCESS;
00371 }
00372 
00373 OStatus OPENR::UnobservePowerStatus(const OServiceEntry& entry)
00374 {
00375         OStatus retval = oINVALID_ARG;
00376 
00377         LOCK(powerStatusObservers);
00378 
00379         map<OServiceEntry, OPowerStatus>::iterator it = powerStatusObservers.find(entry);
00380         if (it != powerStatusObservers.end()) {
00381                 powerStatusObservers.erase(it);
00382                 retval = oSUCCESS;
00383         }
00384 
00385         UNLOCK(powerStatusObservers);
00386 
00387         return retval;
00388 }
00389 
00390 OStatus OPENR::FindDesignData(const char* keyword, ODesignDataID* dataID, byte** data, size_t* size)
00391 {
00392         if (!strcmp(keyword, odesignkeywordCPUINFO)) {
00393                 //TODO
00394                 return oFAIL;
00395         }
00396 
00397         char *path = resolve_case_insensitive_path("MS/OPEN-R/MW/CONF/DESIGNDB.CFG");
00398         fstream DB(path);
00399         free(path);
00400 
00401         if (!DB) {
00402                 return oFAIL;
00403         }
00404 
00405         //parse the design DB file
00406         string line;
00407         bool mySection = true; // starts on a top level section
00408 
00409         const size_t keyword_len = strlen(keyword);
00410 
00411         while(getNonEmptyLine(DB, line, true, &mySection)) {
00412                 if (!strncmp(keyword, line.c_str(), keyword_len) && isspace(line[keyword_len])) {
00413                         char *name = (char*)line.c_str() + keyword_len + 1;
00414 
00415                         while (isspace(*name)) ++name; // skip spaces between keywords and path
00416                         ++name;
00417 
00418                         *data = (byte*)file_get_contents(name, size);
00419                         if (!*data) {
00420                                 return (size == 0 ? oDESIGNDATA_SIZE_ZERO : oNOT_FOUND);
00421                         }
00422 
00423                         // save the pointer+size for later unmaping
00424                         *dataID = MOD_DATA(lastDesignDataID)++;
00425                         DesignData tmp = {*data, *size};
00426                         MOD_DATA(designDataIDs)[*dataID] = tmp;
00427 
00428                         return oSUCCESS;
00429                 }
00430         }
00431         return oNOT_FOUND;
00432 }
00433 
00434 OStatus OPENR::DeleteDesignData(ODesignDataID dataID)
00435 {
00436         map<ODesignDataID, DesignData>::iterator it = MOD_DATA(designDataIDs).find(dataID);
00437 
00438         // dataID invalid/not found
00439         if (it == MOD_DATA(designDataIDs).end()) {
00440                 return oINVALID_ARG;
00441         }
00442 
00443         DesignData data = it->second;
00444 
00445         if (!file_unmap_contents(data.base, data.size)) {
00446                 return oFAIL;
00447         }
00448 
00449         MOD_DATA(designDataIDs).erase(it);
00450         return oSUCCESS;
00451 }
00452 
00453 OStatus OPENR::GetRobotDesign(char* robotDesign)
00454 {
00455         strcpy(robotDesign, ROBOTDESIGN);
00456         return oSUCCESS;
00457 }
00458 
00459 OStatus OPENR::GetMemoryStickStatus(OMemoryStickStatus* status)
00460 {
00461         //TODO
00462         return oFAIL;
00463 }
00464 
00465 OStatus OPENR::Fatal(OFatal fatal)
00466 {
00467         //TODO
00468         return oFAIL;
00469 }
00470 
00471 OStatus OPENR::SetTime(const OTime& time)
00472 {
00473         return ::SetTime(time);
00474 }
00475 
00476 OStatus OPENR::GetTime(OTime* time_)
00477 {
00478         time_->Set(::getSystemTime().seconds, 0);
00479         return oSUCCESS;
00480 }
00481 
00482 OStatus OPENR::SetTimeDifference(sbyte timeDifference)
00483 {
00484         if (::SetTimeDifference(timeDifference) == oSUCCESS) {
00485                 sendPowerStatusNotifications(timeDif, opsoTIME_DIF_NOTIFY_EVERY_CHANGE);
00486                 return oSUCCESS;
00487         }
00488 
00489         return oFAIL;
00490 }
00491 
00492 OStatus OPENR::GetTimeDifference(sbyte* timeDifference)
00493 {
00494         *timeDifference = ::GetTimeDifference();
00495         return oSUCCESS;
00496 }
00497 
00498 OStatus OPENR::SetVolumeSwitch(OVolumeSwitch volSW)
00499 {
00500         //TODO: this should report the new value to the sound server
00501 
00502         if (volSW != ovolumeSW0 && volSW != ovolumeSW1 && volSW != ovolumeSW2 && volSW != ovolumeSW3) {
00503                 return oFAIL;
00504         }
00505 
00506         if (myVolume != volSW) {
00507                 myVolume = volSW;
00508                 sendPowerStatusNotifications(volume, opsoVOLUME_NOTIFY_EVERY_CHANGE);
00509         }
00510         return oSUCCESS;
00511 }
00512 
00513 OStatus OPENR::GetVolumeSwitch(OVolumeSwitch* volSW)
00514 {
00515         *volSW = myVolume;
00516         return oSUCCESS;
00517 }

Generated on Sun Dec 2 23:04:30 2007 for openSDK by  doxygen 1.3.9.1