/*----- PROTECTED REGION ID(USB2.cpp) ENABLED START -----*/ //============================================================================= // // file : USB2.cpp // // description : C++ source for the USB2 class and its commands. // The class is derived from Device. It represents the // CORBA servant object which will be accessed from the // network. All commands which can be executed on the // USB2 are implemented in this file. // // project : // // This file is part of Tango device class. // // Tango is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Tango is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Tango. If not, see <http://www.gnu.org/licenses/>. // // $Author: alessio $ // // $Revision: 1.5 $ // $Date: 2018-10-24 08:12:41 $ // // $HeadURL: $ // //============================================================================= // This file is generated by POGO // (Program Obviously used to Generate tango Object) //============================================================================= #include <USB2.h> #include <USB2Class.h> /*----- PROTECTED REGION END -----*/ // USB2.cpp /** * USB2 class description: * */ //================================================================ // The following table gives the correspondence // between command and method names. // // Command name | Method name //================================================================ // Write | write // Read | read // ReadUntil | read_until //================================================================ //================================================================ // Attributes managed are: //================================================================ // InputLength | Tango::DevLong Scalar // OutputLength | Tango::DevLong Scalar // Reconnections | Tango::DevLong Scalar //================================================================ namespace USB2_ns { /*----- PROTECTED REGION ID(USB2::namespace_starting) ENABLED START -----*/ // static initializations /*----- PROTECTED REGION END -----*/ // USB2::namespace_starting //-------------------------------------------------------- /** * Method : USB2::USB2() * Description: Constructors for a Tango device * implementing the classUSB2 */ //-------------------------------------------------------- USB2::USB2(Tango::DeviceClass *cl, std::string &s) : TANGO_BASE_CLASS(cl, s.c_str()) { /*----- PROTECTED REGION ID(USB2::constructor_1) ENABLED START -----*/ reconnections = -1; init_device(); /*----- PROTECTED REGION END -----*/ // USB2::constructor_1 } //-------------------------------------------------------- USB2::USB2(Tango::DeviceClass *cl, const char *s) : TANGO_BASE_CLASS(cl, s) { /*----- PROTECTED REGION ID(USB2::constructor_2) ENABLED START -----*/ reconnections = -1; init_device(); /*----- PROTECTED REGION END -----*/ // USB2::constructor_2 } //-------------------------------------------------------- USB2::USB2(Tango::DeviceClass *cl, const char *s, const char *d) : TANGO_BASE_CLASS(cl, s, d) { /*----- PROTECTED REGION ID(USB2::constructor_3) ENABLED START -----*/ reconnections = -1; init_device(); /*----- PROTECTED REGION END -----*/ // USB2::constructor_3 } //-------------------------------------------------------- USB2::~USB2() { delete_device(); } //-------------------------------------------------------- /** * Method : USB2::delete_device() * Description: will be called at device destruction or at init command */ //-------------------------------------------------------- void USB2::delete_device() { DEBUG_STREAM << "USB2::delete_device() " << device_name << std::endl; /*----- PROTECTED REGION ID(USB2::delete_device) ENABLED START -----*/ close(); delete[] buffer; /*----- PROTECTED REGION END -----*/ // USB2::delete_device delete[] attr_InputLength_read; delete[] attr_OutputLength_read; delete[] attr_Reconnections_read; } //-------------------------------------------------------- /** * Method : USB2::init_device() * Description: will be called at device initialization. */ //-------------------------------------------------------- void USB2::init_device() { DEBUG_STREAM << "USB2::init_device() create device " << device_name << std::endl; /*----- PROTECTED REGION ID(USB2::init_device_before) ENABLED START -----*/ // Initialization before get_device_property() call ctx = NULL; dev_handle = NULL; buffer = NULL; init_error.clear(); /*----- PROTECTED REGION END -----*/ // USB2::init_device_before // Get the device properties from database get_device_property(); attr_InputLength_read = new Tango::DevLong[1]; attr_OutputLength_read = new Tango::DevLong[1]; attr_Reconnections_read = new Tango::DevLong[1]; // No longer if mandatory property not set. if (mandatoryNotDefined) return; /*----- PROTECTED REGION ID(USB2::init_device) ENABLED START -----*/ // Initialize device try { buffer = new unsigned char[maxPacketSize]; open(); } catch (Tango::DevFailed &e) { init_error = "Initialization failed: " + string(e.errors[0].desc); } catch (...) { init_error = "Initialization failed: Unknown error"; } /*----- PROTECTED REGION END -----*/ // USB2::init_device } //-------------------------------------------------------- /** * Method : USB2::get_device_property() * Description: Read database to initialize property data members. */ //-------------------------------------------------------- void USB2::get_device_property() { /*----- PROTECTED REGION ID(USB2::get_device_property_before) ENABLED START -----*/ // Initialize property data members /*----- PROTECTED REGION END -----*/ // USB2::get_device_property_before mandatoryNotDefined = false; // Read device properties from database. Tango::DbData dev_prop; dev_prop.push_back(Tango::DbDatum("Timeout")); dev_prop.push_back(Tango::DbDatum("VendorID")); dev_prop.push_back(Tango::DbDatum("ProductID")); dev_prop.push_back(Tango::DbDatum("Interface")); dev_prop.push_back(Tango::DbDatum("EndpointUP")); dev_prop.push_back(Tango::DbDatum("EndpointDOWN")); dev_prop.push_back(Tango::DbDatum("MaxPacketSize")); // is there at least one property to be read ? if (dev_prop.size()>0) { // Call database and extract values if (Tango::Util::instance()->_UseDb==true) get_db_device()->get_property(dev_prop); // get instance on USB2Class to get class property Tango::DbDatum def_prop, cl_prop; USB2Class *ds_class = (static_cast<USB2Class *>(get_device_class())); int i = -1; // Try to initialize Timeout from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty()==false) cl_prop >> timeout; else { // Try to initialize Timeout from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty()==false) def_prop >> timeout; } // And try to extract Timeout value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> timeout; // Property StartDsPath is mandatory, check if has been defined in database. check_mandatory_property(cl_prop, dev_prop[i]); // Try to initialize VendorID from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty()==false) cl_prop >> vendorID; else { // Try to initialize VendorID from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty()==false) def_prop >> vendorID; } // And try to extract VendorID value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> vendorID; // Property StartDsPath is mandatory, check if has been defined in database. check_mandatory_property(cl_prop, dev_prop[i]); // Try to initialize ProductID from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty()==false) cl_prop >> productID; else { // Try to initialize ProductID from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty()==false) def_prop >> productID; } // And try to extract ProductID value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> productID; // Property StartDsPath is mandatory, check if has been defined in database. check_mandatory_property(cl_prop, dev_prop[i]); // Try to initialize Interface from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty()==false) cl_prop >> interface; else { // Try to initialize Interface from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty()==false) def_prop >> interface; } // And try to extract Interface value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> interface; // Property StartDsPath is mandatory, check if has been defined in database. check_mandatory_property(cl_prop, dev_prop[i]); // Try to initialize EndpointUP from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty()==false) cl_prop >> endpointUP; else { // Try to initialize EndpointUP from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty()==false) def_prop >> endpointUP; } // And try to extract EndpointUP value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> endpointUP; // Property StartDsPath is mandatory, check if has been defined in database. check_mandatory_property(cl_prop, dev_prop[i]); // Try to initialize EndpointDOWN from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty()==false) cl_prop >> endpointDOWN; else { // Try to initialize EndpointDOWN from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty()==false) def_prop >> endpointDOWN; } // And try to extract EndpointDOWN value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> endpointDOWN; // Property StartDsPath is mandatory, check if has been defined in database. check_mandatory_property(cl_prop, dev_prop[i]); // Try to initialize MaxPacketSize from class property cl_prop = ds_class->get_class_property(dev_prop[++i].name); if (cl_prop.is_empty()==false) cl_prop >> maxPacketSize; else { // Try to initialize MaxPacketSize from default device value def_prop = ds_class->get_default_device_property(dev_prop[i].name); if (def_prop.is_empty()==false) def_prop >> maxPacketSize; } // And try to extract MaxPacketSize value from database if (dev_prop[i].is_empty()==false) dev_prop[i] >> maxPacketSize; // Property StartDsPath is mandatory, check if has been defined in database. check_mandatory_property(cl_prop, dev_prop[i]); } /*----- PROTECTED REGION ID(USB2::get_device_property_after) ENABLED START -----*/ // Check device property data members init vid = stoi(vendorID, NULL, 16); pid = stoi(productID, NULL, 16); ep_up = stoi(endpointUP, NULL, 16); ep_down = stoi(endpointDOWN, NULL, 16); /*----- PROTECTED REGION END -----*/ // USB2::get_device_property_after } //-------------------------------------------------------- /** * Method : USB2::check_mandatory_property() * Description: For mandatory properties check if defined in database. */ //-------------------------------------------------------- void USB2::check_mandatory_property(Tango::DbDatum &class_prop, Tango::DbDatum &dev_prop) { // Check if all properties are empty if (class_prop.is_empty() && dev_prop.is_empty()) { TangoSys_OMemStream tms; tms << std::endl <<"Property \'" << dev_prop.name; if (Tango::Util::instance()->_UseDb==true) tms << "\' is mandatory but not defined in database"; else tms << "\' is mandatory but cannot be defined without database"; append_status(tms.str()); mandatoryNotDefined = true; /*----- PROTECTED REGION ID(USB2::check_mandatory_property) ENABLED START -----*/ cerr << tms.str() << " for " << device_name << endl; /*----- PROTECTED REGION END -----*/ // USB2::check_mandatory_property } } //-------------------------------------------------------- /** * Method : USB2::always_executed_hook() * Description: method always executed before any command is executed */ //-------------------------------------------------------- void USB2::always_executed_hook() { DEBUG_STREAM << "USB2::always_executed_hook() " << device_name << std::endl; if (mandatoryNotDefined) { Tango::Except::throw_exception( (const char *)"PROPERTY_NOT_SET", get_status().c_str(), (const char *)"USB2::always_executed_hook()"); } /*----- PROTECTED REGION ID(USB2::always_executed_hook) ENABLED START -----*/ // code always executed before all requests if (! init_error.empty()) { set_state(Tango::FAULT); set_status(init_error); return; } try { if (! dev_handle) { open(); } } catch(Tango::DevFailed &e) { set_state(Tango::FAULT); set_status(string(e.errors[0].desc)); } catch(...) { set_state(Tango::FAULT); set_status("The device is in FAULT state for unknown reason"); } /*----- PROTECTED REGION END -----*/ // USB2::always_executed_hook } //-------------------------------------------------------- /** * Method : USB2::read_attr_hardware() * Description: Hardware acquisition for attributes */ //-------------------------------------------------------- void USB2::read_attr_hardware(TANGO_UNUSED(std::vector<long> &attr_list)) { DEBUG_STREAM << "USB2::read_attr_hardware(std::vector<long> &attr_list) entering... " << std::endl; /*----- PROTECTED REGION ID(USB2::read_attr_hardware) ENABLED START -----*/ // Add your own code /*----- PROTECTED REGION END -----*/ // USB2::read_attr_hardware } //-------------------------------------------------------- /** * Read attribute InputLength related method * * * Data type: Tango::DevLong * Attr type: Scalar */ //-------------------------------------------------------- void USB2::read_InputLength(Tango::Attribute &attr) { DEBUG_STREAM << "USB2::read_InputLength(Tango::Attribute &attr) entering... " << std::endl; /*----- PROTECTED REGION ID(USB2::read_InputLength) ENABLED START -----*/ // Set the attribute value attr_InputLength_read[0] = input_queue_length(); attr.set_value(attr_InputLength_read); /*----- PROTECTED REGION END -----*/ // USB2::read_InputLength } //-------------------------------------------------------- /** * Read attribute OutputLength related method * * * Data type: Tango::DevLong * Attr type: Scalar */ //-------------------------------------------------------- void USB2::read_OutputLength(Tango::Attribute &attr) { DEBUG_STREAM << "USB2::read_OutputLength(Tango::Attribute &attr) entering... " << std::endl; /*----- PROTECTED REGION ID(USB2::read_OutputLength) ENABLED START -----*/ // Set the attribute value attr_OutputLength_read[0] = output_queue_length(); attr.set_value(attr_OutputLength_read); /*----- PROTECTED REGION END -----*/ // USB2::read_OutputLength } //-------------------------------------------------------- /** * Read attribute Reconnections related method * * * Data type: Tango::DevLong * Attr type: Scalar */ //-------------------------------------------------------- void USB2::read_Reconnections(Tango::Attribute &attr) { DEBUG_STREAM << "USB2::read_Reconnections(Tango::Attribute &attr) entering... " << std::endl; /*----- PROTECTED REGION ID(USB2::read_Reconnections) ENABLED START -----*/ // Set the attribute value attr_Reconnections_read[0] = reconnections; attr.set_value(attr_Reconnections_read); /*----- PROTECTED REGION END -----*/ // USB2::read_Reconnections } //-------------------------------------------------------- /** * Method : USB2::add_dynamic_attributes() * Description: Create the dynamic attributes if any * for specified device. */ //-------------------------------------------------------- void USB2::add_dynamic_attributes() { /*----- PROTECTED REGION ID(USB2::add_dynamic_attributes) ENABLED START -----*/ // Add your own code to create and add dynamic attributes if any /*----- PROTECTED REGION END -----*/ // USB2::add_dynamic_attributes } //-------------------------------------------------------- /** * Command Write related method * * * @param argin */ //-------------------------------------------------------- void USB2::write(const Tango::DevVarCharArray *argin) { DEBUG_STREAM << "USB2::Write() - " << device_name << std::endl; /*----- PROTECTED REGION ID(USB2::write) ENABLED START -----*/ check_init(); if(!timeout) { Tango::Except::throw_exception( "", "Invalid timeout", "USB2::write()"); } unsigned char *argin_data = new unsigned char[argin->length()]; for(unsigned int i=0; i<argin->length(); ++i) { argin_data[i] = (*argin)[i]; } int bytes_total = 0, bytes_to_write = argin->length(); while(bytes_total != bytes_to_write) { int bytes_written; int ret = libusb_bulk_transfer(dev_handle, ep_down, argin_data + bytes_total, bytes_to_write - bytes_total, &bytes_written, timeout); if(ret != 0 || bytes_written != bytes_to_write - bytes_total) { delete argin_data; string error_mesg = "Unable to send request to device"; close(); open(); DEBUG_STREAM << error_mesg << endl; set_state( Tango::FAULT ); set_status( error_mesg ); Tango::Except::throw_exception( "", error_mesg, "USB2::write()"); } bytes_total += bytes_written; } delete argin_data; /*----- PROTECTED REGION END -----*/ // USB2::write } //-------------------------------------------------------- /** * Command Read related method * * * @param argin * @returns */ //-------------------------------------------------------- Tango::DevVarCharArray *USB2::read(Tango::DevLong argin) { Tango::DevVarCharArray *argout; DEBUG_STREAM << "USB2::Read() - " << device_name << std::endl; /*----- PROTECTED REGION ID(USB2::read) ENABLED START -----*/ check_init(); if(!timeout) { Tango::Except::throw_exception( "", "Invalid timeout", "USB2::write()"); } if (argin < 0) { Tango::Except::throw_exception("", "Input has to be in positive range", "USB2::read()"); } while( (size_t)argin > data.size() ) { int bytes_readed; int ret = libusb_bulk_transfer(dev_handle, ep_up, buffer, maxPacketSize, &bytes_readed, timeout); if(ret != 0 || bytes_readed == 0) { string error_mesg( "No response from device" ); DEBUG_STREAM << error_mesg << endl; Tango::Except::throw_exception("", error_mesg, "USB2::read()"); } for(int i=0;i<bytes_readed;++i) { data.push_back(buffer[i]); } } argout = new Tango::DevVarCharArray(); argout->length(argin); for( int i=0; i<argin; ++i ) { (*argout)[i] = data[i]; } data.erase( data.begin(), data.begin() + argin ); /*----- PROTECTED REGION END -----*/ // USB2::read return argout; } //-------------------------------------------------------- /** * Command ReadUntil related method * * * @param argin * @returns */ //-------------------------------------------------------- Tango::DevVarCharArray *USB2::read_until(const Tango::DevVarCharArray *argin) { Tango::DevVarCharArray *argout; DEBUG_STREAM << "USB2::ReadUntil() - " << device_name << std::endl; /*----- PROTECTED REGION ID(USB2::read_until) ENABLED START -----*/ check_init(); if(!timeout) { Tango::Except::throw_exception( "", "Invalid timeout", "USB2::write()"); } if (argin->length() != 1) { Tango::Except::throw_exception("", "Delimiter has to be one byte length", "USB2::read_until()"); } char delim = (*argin)[0]; bool found = false; size_t pos; while( ! found ) { for( pos = 0; pos < data.size(); ++pos ) { if (memcmp(&data[pos], &delim, 1) == 0) { found = true; break; } } if ( ! found ) { int bytes_readed; int ret = libusb_bulk_transfer(dev_handle, ep_up, buffer, maxPacketSize, &bytes_readed, timeout); if(ret != 0 || bytes_readed == 0) { string error_mesg( "No response from device" ); DEBUG_STREAM << error_mesg << endl; Tango::Except::throw_exception("", error_mesg, "USB2::read_until()"); } for(int i=0;i<bytes_readed;++i) { data.push_back(buffer[i]); } } } argout = new Tango::DevVarCharArray(); argout->length( pos+1 ); for( size_t i = 0; i < pos + 1; ++i ) { (*argout)[i] = data[i]; } data.erase( data.begin(), data.begin() + pos + 1 ); /*----- PROTECTED REGION END -----*/ // USB2::read_until return argout; } //-------------------------------------------------------- /** * Method : USB2::add_dynamic_commands() * Description: Create the dynamic commands if any * for specified device. */ //-------------------------------------------------------- void USB2::add_dynamic_commands() { /*----- PROTECTED REGION ID(USB2::add_dynamic_commands) ENABLED START -----*/ // Add your own code to create and add dynamic commands if any /*----- PROTECTED REGION END -----*/ // USB2::add_dynamic_commands } /*----- PROTECTED REGION ID(USB2::namespace_ending) ENABLED START -----*/ // Additional Methods void USB2::check_init() { if (! init_error.empty() ) { DEBUG_STREAM << init_error << endl; Tango::Except::throw_exception( "", init_error.c_str(), "USB2::check_init()"); } } void USB2::open() { DEBUG_STREAM << "Opening USB device..." << endl; if(libusb_init(&ctx) < 0) { string error_mesg = "Failed to initialize libusb"; ERROR_STREAM << error_mesg << endl; assert( false); Tango::Except::throw_exception( "", error_mesg, "USB2::open()"); } #ifndef NDEBUG libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_WARNING); #endif dev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid); if(dev_handle == NULL) { libusb_exit(ctx); string error_mesg = "Unable to open device"; ERROR_STREAM << error_mesg << endl; assert( false); Tango::Except::throw_exception( "", error_mesg, "USB2::open()"); } if(libusb_claim_interface(dev_handle, interface) < 0) { libusb_release_interface(dev_handle, interface); libusb_close(dev_handle); libusb_exit(ctx); string error_mesg = "Failed to claim interface"; ERROR_STREAM << error_mesg << endl; assert( false); Tango::Except::throw_exception( "", error_mesg, "USB2::open()"); } DEBUG_STREAM << "USB device opened." << endl; reconnections++; set_state(Tango::ON); set_status("The device in ON state"); } void USB2::close() { DEBUG_STREAM << "Closing USB device..." << endl; int input_len = input_queue_length(); int output_len = output_queue_length(); if( input_len + output_len) { WARN_STREAM << " Bytes dropped: " << input_len << " input, " << output_len << " output" << endl; } if(dev_handle) { libusb_release_interface(dev_handle, interface); libusb_close(dev_handle); libusb_exit(ctx); dev_handle = NULL; } data.clear(); DEBUG_STREAM << "USB device closed" << endl; } int USB2::input_queue_length() { return data.size(); } int USB2::output_queue_length() { return 0; } /*----- PROTECTED REGION END -----*/ // USB2::namespace_ending } // namespace