Initial commit
[remote/remote-mci.git] / diku_mch / DeviceManager.cc
blob02dafd5693489b9ef652b0354544f9bfd63b6437
1 #include "DeviceManager.h"
3 namespace remote { namespace diku_mch {
5 struct del : public std::unary_function<std::pair<const uint64_t,usbdevice_t*>,void>
7 void operator()(std::pair<const uint64_t,usbdevice_t*> x) { delete x.second; }
8 };
10 struct delMote : public std::unary_function<std::pair<const uint64_t,Mote*>,void>
12 void operator()(std::pair<const uint64_t,Mote*> x) { delete x.second; }
15 struct invalidate : public std::unary_function<std::pair<const uint64_t,Mote*>,void>
17 void operator()(std::pair<const uint64_t,Mote*> x)
18 { if (x.second) x.second->invalidate(); }
22 void DeviceManager::refresh()
24 readUsbDevices();
25 readMoteDevices();
29 void DeviceManager::readUsbDevices()
31 int fd;
32 std::string usbdevices,regx,bus,prnt,port,devno,serialno;
33 boost::match_flag_type flags;
34 std::string::const_iterator start, end;
35 usbdevice_t* device;
37 // erase any existing info
38 std::for_each(devicesByConnection.begin(),devicesByConnection.end(),del());
39 devicesById.clear();
40 devicesByConnection.clear();
42 // read the usb devices file
43 char* buffer = new char[Configuration::vm["maxDeviceFileSize"].as<uint16_t>()];
44 fd = open(Configuration::vm["usbdevicePath"].as<std::string>().c_str(),O_RDONLY | O_NONBLOCK);
45 read(fd,buffer,Configuration::vm["maxDeviceFileSize"].as<uint16_t>()); // non-blocking, so we should have the full contents now
46 close(fd);
47 usbdevices = buffer;
48 delete buffer;
49 // create a regular expression to match the desired information per device
50 regx = ".*?T: .*?Bus=([0-9]*).*?Prnt=([0-9]*) Port=([0-9]*).*?Dev#=[ ]*([0-9]*).*?(^[ ]*$|SerialNumber=([^\\n]*)).*";
51 boost::regex e(regx, boost::regex::perl);
52 boost::smatch what;
54 flags = boost::match_continuous;
55 start = usbdevices.begin();
56 end = usbdevices.end();
58 // perform the search and register the devices
59 while(boost::regex_search(start,end, what, e, flags))
61 start = what[1].second;
63 devno = what[4].str();
64 bus = what[1].str();
65 prnt = what[2].str();
66 port = what[3].str();
67 serialno = what[6].matched ? what[6].str() : "";
69 device = new usbdevice_t;
70 device->devNo = atoi(devno.c_str());
71 device->bus = atoi(bus.c_str());
72 device->parent = atoi(prnt.c_str());
73 device->port = atoi(port.c_str());
74 device->serial = serialno;
76 /*printf("Registering usb device bus %s, parent %s, port %s, dev# %s, serial %s\n",
77 bus.c_str(),prnt.c_str(),port.c_str(),devno.c_str(),serialno.c_str());*/
78 // register the device in the search structures.
79 devicesById[device->serial] = device;
80 uint64_t key = device->bus;
81 key = key << 8;
82 key |= device->parent;
83 key = key << 8;
84 key |= device->port;
85 devicesByConnection[key] = device;
87 flags |= boost::match_prev_avail;
88 flags |= boost::match_not_bob;
92 void DeviceManager::readMoteDevices()
94 std::string usbserial,regx,tty,hcid,ports,path;
95 std::string::const_iterator start, end;
96 boost::match_flag_type flags;
97 int fd;
98 char *buffer = new char[Configuration::vm["maxDeviceFileSize"].as<uint16_t>()];
100 // invalidate any existing motes
101 std::for_each(motes.begin(),motes.end(),invalidate());
102 // clear new motes and delete and clear lost motes
103 newMotes.clear();
104 std::for_each(lostMotes.begin(),lostMotes.end(),delMote());
105 lostMotes.clear();
106 // open the file describing connected usbserial devices
107 fd = open(Configuration::vm["usbserialPath"].as<std::string>().c_str(),O_RDONLY | O_NONBLOCK);
108 read(fd,buffer,Configuration::vm["maxDeviceFileSize"].as<uint16_t>()); // non-blocking, so we should have the file now
109 close(fd);
110 usbserial = buffer;
112 delete buffer;
114 regx = ".*?([0-9]): .*?vendor:";
115 regx += Configuration::vm["vendorId"].as<std::string>();
116 regx += " .*?product:";
117 regx += Configuration::vm["productId"].as<std::string>();
118 regx += ".*?path:(usb-(([0-9]|[a-f]|\\.|:)*)-(([0-9]|\\.)*)[^\\n]*).*";
120 boost::regex e(regx, boost::regex::perl);
121 boost::smatch what;
123 flags = boost::match_continuous;
125 start = usbserial.begin();
126 end = usbserial.end();
128 while(boost::regex_search(start,end, what, e, flags))
130 start = what[1].second;
132 tty = what[1].matched ? what[1].str() : "";
133 hcid = what[3].matched ? what[3].str() : "";
134 ports = what[5].matched ? what[5].str() : "";
135 path = what[2].matched ? what[2].str() : "";
136 flags |= boost::match_prev_avail;
137 flags |= boost::match_not_bob;
139 // now, we did find a device with the right vendor and product id
140 // - look up the host controller
141 // and use this to traverse to the corresponding usb device entry
143 usbserialmap_t::const_iterator r = devicesById.find(hcid);
145 if (r == devicesById.end()) __THROW__ ("Go away! You don't exist!\n");
147 usbdevice_t* rootDev = r->second;
149 usbdevice_t* moteDev = findUsbDevice(rootDev,ports.begin(),ports.end());
150 if (moteDev)
152 uint64_t mac = Configuration::vm["macPrefix"].as<uint64_t>();
153 mac = mac << 32;
154 mac |= strtoll(moteDev->serial.c_str(),NULL,16);
155 // Time to update the mote collection
156 motemap_t::iterator m = motes.find(mac);
157 if (m != motes.end())
159 // we found a mote with the same MAC address
160 // just make sure the info is up-to-date
161 m->second->validate( path, atoi(tty.c_str()) );
163 else
165 Mote* mote = new Mote( mac, path, atoi(tty.c_str()) );
166 if (mote->_open() == SUCCESS)
168 // this must be a new mote, add it to the collection
169 motemap_t::value_type elm(mac,mote);
170 motes.insert(elm);
171 newMotes.insert(elm);
173 else
175 delete mote;
181 // finally, clean up the motes that were lost since the last refresh
182 motemap_t::iterator moteI = motes.begin();
183 while (moteI != DeviceManager::motes.end())
185 if (moteI->second)
187 if (!moteI->second->isValid())
189 moteI->second->_close();
190 lostMotes.insert(*moteI);
191 motes.erase(moteI);
194 else
196 motes.erase(moteI);
198 moteI++;
202 usbdevice_t* DeviceManager::findUsbDevice( usbdevice_t* dev,
203 std::string::const_iterator start,
204 std::string::const_iterator end )
206 // get the first port of path
207 std::string port, regx;
208 boost::match_flag_type flags;
209 regx = ".*?([0-9])+\\.*.*";
210 boost::regex e(regx, boost::regex::perl);
211 boost::smatch what;
214 flags = boost::match_continuous;
215 if (boost::regex_search(start,end, what, e, flags))
217 // subtract 1 from port because usbserial indexes ports starting with 1 instead of 0!!!
218 uint64_t key = dev->bus;
219 key = key << 8;
220 key |= dev->devNo;
221 key = key << 8;
222 key |= atoi(what[1].str().c_str())-1;
223 usbconnectionmap_t::const_iterator devI = devicesByConnection.find(key);
224 if (devI == devicesByConnection.end()) return NULL; // device does not exist
225 usbdevice_t* nextdev = devI->second;
226 return findUsbDevice(nextdev,what[1].second,end);
228 else
230 return dev;
235 motemap_t DeviceManager::motes;
236 motemap_t DeviceManager::newMotes;
237 motemap_t DeviceManager::lostMotes;
239 usbserialmap_t DeviceManager::devicesById;
240 usbconnectionmap_t DeviceManager::devicesByConnection;