diff --git a/pvAccessApp/ca/caChannel.cpp b/pvAccessApp/ca/caChannel.cpp index 24e5786..8d4e4f8 100644 --- a/pvAccessApp/ca/caChannel.cpp +++ b/pvAccessApp/ca/caChannel.cpp @@ -70,8 +70,10 @@ static PVStructure::shared_pointer createPVStructure(CAChannel::shared_pointer c } else { - // TODO handle enum + // TODO handle enum array // introduce ackConnected(pvStructure), if non-enum directly call, else when labels are retrieved + StringArray labels; + pvStructure = standardPVField->enumerated(labels, properties); } return pvStructure; @@ -88,14 +90,14 @@ static PVStructure::shared_pointer createPVStructure(CAChannel::shared_pointer c if (dbrType != DBR_CTRL_STRING && dbrType != DBR_CTRL_ENUM) properties = "value,alarm,display,valueAlarm,control"; else - properties = "value,alarm,display"; + properties = "value,alarm"; } else if (dbrType >= DBR_GR_STRING) // 21 { - if (dbrType != DBR_GR_STRING && dbrType != DBR_GR_STRING) + if (dbrType != DBR_GR_STRING && dbrType != DBR_GR_ENUM) properties = "value,alarm,display,valueAlarm"; else - properties = "value,alarm,display"; + properties = "value,alarm"; } else if (dbrType >= DBR_TIME_STRING) // 14 properties = "value,timeStamp"; @@ -115,11 +117,11 @@ void CAChannel::connected() elementCount = ca_element_count(channelID); channelType = ca_field_type(channelID); - // no valueAlarm and control for non-numeric type + // no valueAlarm and control,display for non-numeric type String allProperties = - channelType != DBR_STRING && channelType != DBR_ENUM ? + (channelType != DBR_STRING && channelType != DBR_ENUM) ? "value,timeStamp,alarm,display,valueAlarm,control" : - "value,timeStamp,alarm,display"; + "value,timeStamp,alarm"; PVStructure::shared_pointer pvStructure = createPVStructure(shared_from_this(), allProperties); // TODO thread sync @@ -289,13 +291,9 @@ ChannelGet::shared_pointer CAChannel::createChannelGet( ChannelPut::shared_pointer CAChannel::createChannelPut( ChannelPutRequester::shared_pointer const & channelPutRequester, - epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/) + epics::pvData::PVStructure::shared_pointer const & pvRequest) { - Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented"); - ChannelPut::shared_pointer nullChannelPut; - EXCEPTION_GUARD(channelPutRequester->channelPutConnect(errorStatus, nullChannelPut, - PVStructure::shared_pointer(), BitSet::shared_pointer())); - return nullChannelPut; + return CAChannelPut::create(shared_from_this(), channelPutRequester, pvRequest); } ChannelPutGet::shared_pointer CAChannel::createChannelPutGet( @@ -411,7 +409,6 @@ ChannelGet::shared_pointer CAChannelGet::create( ChannelGetRequester::shared_pointer const & channelGetRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { - // TODO for not pvRequest ignored ChannelGet::shared_pointer thisPtr(new CAChannelGet(channel, channelGetRequester, pvRequest)); static_cast(thisPtr.get())->activate(); return thisPtr; @@ -485,7 +482,7 @@ static void ca_get_handler(struct event_handler_args args) channelGet->getDone(args); } -typedef void (*copyDBRtoPVStructure)(const void * from, unsigned count, PVStructure::shared_pointer const & tp); +typedef void (*copyDBRtoPVStructure)(const void * from, unsigned count, PVStructure::shared_pointer const & to); // template @@ -750,18 +747,18 @@ static copyDBRtoPVStructure copyFuncTable[] = copy_DBR_TIME, // DBR_TIME_LONG copy_DBR_TIME, // DBR_TIME_DOUBLE - copy_DBR_TIME, // DBR_GR_STRING -> DBR_STS_STRING + copy_DBR_STS, // DBR_GR_STRING -> DBR_STS_STRING copy_DBR_GR, // DBR_GR_INT, DBR_GR_SHORT copy_DBR_GR, // DBR_GR_FLOAT - 0,// TODO copy_DBR_GR, // DBR_GR_ENUM + copy_DBR_STS, // DBR_GR_ENUM -> DBR_STS_ENUM copy_DBR_GR, // DBR_GR_CHAR copy_DBR_GR, // DBR_GR_LONG copy_DBR_GR, // DBR_GR_DOUBLE - copy_DBR_TIME, // DBR_CTRL_STRING -> DBR_STS_STRING + copy_DBR_STS, // DBR_CTRL_STRING -> DBR_STS_STRING copy_DBR_CTRL, // DBR_CTRL_INT, DBR_CTRL_SHORT copy_DBR_CTRL, // DBR_CTRL_FLOAT - 0,// TODO copy_DBR_CTRL, // DBR_CTRL_ENUM + copy_DBR_STS, // DBR_CTRL_ENUM -> DBR_STS_ENUM copy_DBR_CTRL, // DBR_CTRL_CHAR copy_DBR_CTRL, // DBR_CTRL_LONG copy_DBR_CTRL // DBR_CTRL_DOUBLE @@ -785,7 +782,6 @@ void CAChannelGet::getDone(struct event_handler_args &args) } else { - // TODO check: ca_message from args.status Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(args.status))); EXCEPTION_GUARD(channelGetRequester->getDone(errorStatus)); } @@ -834,3 +830,218 @@ void CAChannelGet::unlock() { // TODO } + + + + + + + + + + + + +ChannelPut::shared_pointer CAChannelPut::create( + CAChannel::shared_pointer const & channel, + ChannelPutRequester::shared_pointer const & channelPutRequester, + epics::pvData::PVStructure::shared_pointer const & pvRequest) +{ + ChannelPut::shared_pointer thisPtr(new CAChannelPut(channel, channelPutRequester, pvRequest)); + static_cast(thisPtr.get())->activate(); + return thisPtr; +} + + +CAChannelPut::~CAChannelPut() +{ + // TODO +} + + +CAChannelPut::CAChannelPut(CAChannel::shared_pointer const & _channel, + ChannelPutRequester::shared_pointer const & _channelPutRequester, + epics::pvData::PVStructure::shared_pointer const & pvRequest) : + channel(_channel), + channelPutRequester(_channelPutRequester), + getType(getDBRType(pvRequest, _channel->getNativeType())), + pvStructure(createPVStructure(_channel, getType)), + bitSet(new BitSet(pvStructure->getStructure()->getNumberFields())) +{ + // NOTE: we require value type, we can only put value field + bitSet->set(pvStructure->getSubField("value")->getFieldOffset()); +} + +void CAChannelPut::activate() +{ + EXCEPTION_GUARD(channelPutRequester->channelPutConnect(Status::Ok, shared_from_this(), + pvStructure, bitSet)); +} + + +/* --------------- epics::pvAccess::ChannelPut --------------- */ + + +static void ca_put_handler(struct event_handler_args args) +{ + CAChannelPut *channelPut = static_cast(args.usr); + channelPut->putDone(args); +} + + +static void ca_put_get_handler(struct event_handler_args args) +{ + CAChannelPut *channelPut = static_cast(args.usr); + channelPut->getDone(args); +} + +typedef int (*doPut)(CAChannel::shared_pointer const & channel, void *usrArg, PVStructure::shared_pointer const & from); + + +// template +template +int doPut_pvStructure(CAChannel::shared_pointer const & channel, void *usrArg, PVStructure::shared_pointer const & pvStructure) +{ + bool isScalarValue = pvStructure->getStructure()->getField("value")->getType() == scalar; + + if (isScalarValue) + { + std::tr1::shared_ptr value = std::tr1::static_pointer_cast(pvStructure->getSubField("value")); + + // TODO error handling + pT val = value->get(); + int result = ca_array_put_callback(channel->getNativeType(), 1, + channel->getChannelID(), &val, + ca_put_handler, usrArg); + + if (result == ECA_NORMAL) + { + ca_flush_io(); + } + + return result; + } + else + { + /*TODO + std::tr1::shared_ptr value = + std::tr1::static_pointer_cast(pvStructure->getScalarArrayField("value", sT)); + value->put(0, count, static_cast(dbr), 0); + */ + + return ECA_NOSUPPORT; + } +} + +static doPut doPutFuncTable[] = +{ + 0, //doPut_pvStructure, // DBR_STRING + doPut_pvStructure, // DBR_INT, DBR_SHORT + doPut_pvStructure, // DBR_FLOAT + 0, //doPut_pvStructure, // DBR_ENUM + doPut_pvStructure, // DBR_CHAR + doPut_pvStructure, // DBR_LONG + doPut_pvStructure, // DBR_DOUBLE +}; + +void CAChannelPut::putDone(struct event_handler_args &args) +{ + if (args.status == ECA_NORMAL) + { + EXCEPTION_GUARD(channelPutRequester->putDone(Status::Ok)); + } + else + { + Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(args.status))); + EXCEPTION_GUARD(channelPutRequester->putDone(errorStatus)); + } +} + + +void CAChannelPut::put(bool lastRequest) +{ + doPut putFunc = doPutFuncTable[channel->getNativeType()]; + if (putFunc) + { + int result = putFunc(channel, this, pvStructure); + if (result != ECA_NORMAL) + { + Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(result))); + EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus)); + } + } + else + { + // TODO remove + std::cout << "no put func implemented" << std::endl; + } + + // TODO here???!!! + //if (lastRequest) + // destroy(); +} + + +void CAChannelPut::getDone(struct event_handler_args &args) +{ + if (args.status == ECA_NORMAL) + { + copyDBRtoPVStructure copyFunc = copyFuncTable[getType]; + if (copyFunc) + copyFunc(args.dbr, args.count, pvStructure); + else + { + // TODO remove + std::cout << "no copy func implemented" << std::endl; + } + + // TODO + EXCEPTION_GUARD(channelPutRequester->getDone(Status::Ok)); + } + else + { + Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(args.status))); + EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus)); + } +} + + +void CAChannelPut::get() +{ + // TODO error handling + int result = ca_array_get_callback(getType, channel->getElementCount(), + channel->getChannelID(), ca_put_get_handler, this); + if (result == ECA_NORMAL) + { + ca_flush_io(); + } + else + { + Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(result))); + EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus)); + } +} + + +/* --------------- epics::pvData::Destroyable --------------- */ + + +void CAChannelPut::destroy() +{ + // TODO +} + + +/* --------------- epics::pvData::Lockable --------------- */ + + +void CAChannelPut::lock() +{ + // TODO +} + + +void CAChannelPut::unlock() +{ + // TODO +} diff --git a/pvAccessApp/ca/caChannel.h b/pvAccessApp/ca/caChannel.h index d3ee1aa..eb7dd98 100644 --- a/pvAccessApp/ca/caChannel.h +++ b/pvAccessApp/ca/caChannel.h @@ -157,6 +157,55 @@ private: epics::pvData::BitSet::shared_pointer bitSet; }; + + +class CAChannelPut : + public ChannelPut, + public std::tr1::enable_shared_from_this +{ + +public: + POINTER_DEFINITIONS(CAChannelPut); + + static ChannelPut::shared_pointer create(CAChannel::shared_pointer const & channel, + ChannelPutRequester::shared_pointer const & channelPutRequester, + epics::pvData::PVStructure::shared_pointer const & pvRequest); + + virtual ~CAChannelPut(); + + void putDone(struct event_handler_args &args); + void getDone(struct event_handler_args &args); + + /* --------------- epics::pvAccess::ChannelPut --------------- */ + + virtual void put(bool lastRequest); + virtual void get(); + + /* --------------- epics::pvData::Destroyable --------------- */ + + virtual void destroy(); + + /* --------------- epics::pvData::Lockable --------------- */ + + virtual void lock(); + virtual void unlock(); + +private: + + CAChannelPut(CAChannel::shared_pointer const & _channel, + ChannelPutRequester::shared_pointer const & _channelPutRequester, + epics::pvData::PVStructure::shared_pointer const & pvRequest); + void activate(); + + // TODO weak_ptr usage? + CAChannel::shared_pointer channel; + ChannelPutRequester::shared_pointer channelPutRequester; + chtype getType; + + epics::pvData::PVStructure::shared_pointer pvStructure; + epics::pvData::BitSet::shared_pointer bitSet; +}; + }} #endif /* CACHANNEL_H */