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
; }
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()
29 void DeviceManager::readUsbDevices()
32 std::string usbdevices
,regx
,bus
,prnt
,port
,devno
,serialno
;
33 boost::match_flag_type flags
;
34 std::string::const_iterator start
, end
;
37 // erase any existing info
38 std::for_each(devicesByConnection
.begin(),devicesByConnection
.end(),del());
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
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
);
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();
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
;
82 key
|= device
->parent
;
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
;
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
104 std::for_each(lostMotes
.begin(),lostMotes
.end(),delMote());
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
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
);
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());
152 uint64_t mac
= Configuration::vm
["macPrefix"].as
<uint64_t>();
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()) );
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
);
171 newMotes
.insert(elm
);
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())
187 if (!moteI
->second
->isValid())
189 moteI
->second
->_close();
190 lostMotes
.insert(*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
);
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
;
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
);
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
;