RTXI 1.3
plugins/ni_device/ni_driver.cpp
Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2011 Georgia Institute of Technology, University of Utah, Weill Cornell Medical College
00003 
00004  This program is free software: you can redistribute it and/or modify
00005  it under the terms of the GNU General Public License as published by
00006  the Free Software Foundation, either version 3 of the License, or
00007  (at your option) any later version.
00008 
00009  This program is distributed in the hope that it will be useful,
00010  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  GNU General Public License for more details.
00013 
00014  You should have received a copy of the GNU General Public License
00015  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017  */
00018 
00019 #include <ni_device.h>
00020 #include <ni_devices.h>
00021 #include <ni_driver.h>
00022 #include <debug.h>
00023 
00024 #include <fcntl.h>
00025 #include <fstream>
00026 #include <sstream>
00027 
00028 extern "C" Plugin::Object *createRTXIPlugin(void)
00029 {
00030     return new NIDriver();
00031 }
00032 
00033 NIDriver::~NIDriver(void) {
00034     for(std::list<NIDevice *>::iterator i = deviceList.begin();i != deviceList.end();++i)
00035         delete *i;
00036 }
00037 
00038 DAQ::Device *NIDriver::createDevice(const std::list<std::string> &args) {
00039     int bus = -1;
00040     float dev;
00041 
00042     sscanf(args.front().c_str(),"PCI::%d::%f",&bus,&dev);
00043 
00044     if(bus < 0) {
00045         u32 bus_id = (u32)-1;
00046         u32 pci_id;
00047         char buffer[512];
00048         std::ifstream file("/proc/bus/pci/devices");
00049 
00050         while(!file.eof()) {
00051             file.getline(buffer,sizeof(buffer));
00052             sscanf(buffer,"%x %x %*s",&bus_id,&pci_id);
00053 
00054             if((pci_id >> 16) == 0x1093)
00055                 break;
00056         }
00057 
00058         if(bus_id == (u32)-1) {
00059             ERROR_MSG("NIDriver::createDevice : scan for NI devices failed, no devices detected.\n");
00060             return 0;
00061         }
00062 
00063         bus = (bus_id & 0x0000FF00) >> 8;
00064         dev = (bus_id & 0x000000F8) >> 3;
00065     }
00066 
00067     //printf("%s -> BUS : %d DEVICE : %f\n",args.front().c_str(),bus,dev);
00068     //printf("filename : /proc/bus/pci/%02d/%04.1f\n",bus,dev);
00069 
00070     ni_device_t *device_info = 0;
00071     struct {
00072         u16 vendor_id;
00073         u16 device_id;
00074         u32 junk[3];
00075         u32 bar[2];
00076     } pci_info;
00077 
00078     char filename[256];
00079     sprintf(filename,"/proc/bus/pci/%02d/%04.1f",bus,dev);
00080 
00081     int fd;
00082     if((fd = open(filename,O_RDONLY)) < 0) {
00083         ERROR_MSG("NIDriver::createDevice : failed to open %s for reading to acquire device information.\n");
00084         return 0;
00085     }
00086     read(fd,&pci_info,sizeof(pci_info));
00087 
00088     for(size_t i=0;i<ni_devices_size;++i)
00089         if(ni_devices[i].deviceID == pci_info.device_id) {
00090             device_info = ni_devices+i;
00091             break;
00092         }
00093 
00094     if(!device_info) {
00095         ERROR_MSG("NIDriver::createDevice : device (%X) isn't currently supported by this driver.\n",pci_info.device_id);
00096         return 0;
00097     }
00098 
00099     int offset;
00100     size_t dio_count = device_info->dio_count > 32 ? 32 : device_info->dio_count;
00101     size_t num_channels = device_info->ai_count+device_info->ao_count+2*dio_count;
00102     IO::channel_t channels[device_info->ai_count+device_info->ao_count+2*dio_count];
00103 
00104     offset = 0;
00105     for(int i=offset;i<device_info->ai_count+offset;++i) {
00106         std::ostringstream name;
00107         name << "Analog Input " << i-offset;;
00108         channels[i].name = name.str();
00109         channels[i].description = "";
00110         channels[i].flags = IO::OUTPUT;
00111     }
00112     offset += device_info->ai_count;
00113     for(int i=offset;i<device_info->ao_count+offset;++i) {
00114         std::ostringstream name;
00115         name << "Analog Output " << i-offset;
00116         channels[i].name = name.str();
00117         channels[i].description = "";
00118         channels[i].flags = IO::INPUT;
00119     }
00120     offset += device_info->ao_count;
00121     for(int i=offset;i<dio_count+offset;++i) {
00122         std::ostringstream name;
00123         name << "Digital Input/Output " << i-offset;
00124         channels[i].name = name.str();
00125         channels[i].description = "";
00126         channels[i].flags = IO::OUTPUT;
00127     }
00128     offset += dio_count;
00129     for(int i=offset;i<dio_count+offset;++i) {
00130         std::ostringstream name;
00131         name << "Digital Input/Output " << i-offset;
00132         channels[i].name = name.str();
00133         channels[i].description = "";
00134         channels[i].flags = IO::INPUT;
00135     }
00136 
00137     NIDevice *device = new NIDevice(channels,num_channels,args.front().c_str(),device_info,pci_info.bar,sizeof(pci_info.bar)/sizeof(pci_info.bar[0]));
00138     deviceList.push_back(device);
00139     return device;
00140 }
00141 
00142 void NIDriver::doLoad(const Settings::Object::State &s) {
00143     for(size_t i = 0, end = s.loadInteger("Num Devices");i < end;++i) {
00144         std::list<std::string> args;
00145         args.push_back(s.loadString(QString::number(i)));
00146         DAQ::Device *device = createDevice(args);
00147         if(device)
00148             device->load(s.loadState(QString::number(i)));
00149     }
00150 }
00151 
00152 void NIDriver::doSave(Settings::Object::State &s) const {
00153     s.saveInteger("Num Devices",deviceList.size());
00154     size_t n = 0;
00155     for(std::list<NIDevice *>::const_iterator i = deviceList.begin(),end = deviceList.end();i != end; ++i) {
00156         std::ostringstream str;
00157         str << n++;
00158         s.saveString(str.str(),(*i)->getDeviceName());
00159         s.saveState(str.str(),(*i)->save());
00160     }
00161 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines