peripherals  1.4.2
RoadNarrows Robotics Hardware Peripherals Package
ut-HIDXbox360.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Peripherals
4 //
5 /*! \file
6  *
7  * $LastChangedDate: 2014-03-03 09:01:51 -0700 (Mon, 03 Mar 2014) $
8  * $Rev: 3586 $
9  *
10  * \ingroup periphs_ut
11  *
12  * \brief Unit test for libhid xbox360 controller
13  *
14  * \author Daniel Packard (daniel@roadnarrows.com)
15  *
16  * \copyright
17  * \h_copy 2013-2017. RoadNarrows LLC.\n
18  * http://www.roadnarrows.com\n
19  * All Rights Reserved
20  */
21 //
22 // Redistribution and use in source and binary forms, with or without
23 // modification, are permitted provided that the following conditions are met:
24 //
25 // 1. Redistributions of source code must retain the above copyright notice,
26 // this list of conditions and the following disclaimer.
27 //
28 // 2. Redistributions in binary form must reproduce the above copyright notice,
29 // this list of conditions and the following disclaimer in the documentation
30 // and/or other materials provided with the distribution.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
36 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 // POSSIBILITY OF SUCH DAMAGE.
42 //
43 // The views and conclusions contained in the software and documentation are
44 // those of the authors and should not be interpreted as representing official
45 // policies, either expressed or implied, of the FreeBSD Project.
46 
47 #include <iostream>
48 #include <string>
49 
50 #include "rnr/rnrconfig.h"
51 #include "rnr/log.h"
52 
53 #include "rnr/hid/HID.h"
54 #include "rnr/hid/HIDXbox360.h"
55 
56 #include <gtest/gtest.h>
57 
58 using namespace rnr;
59 
60 /*!
61  * \ingroup periphs_ut
62  * \defgroup periphs_ut_libhid_xbox360 Xbox360 Unit Tests
63  * \brief Fine-grained testing of xbox360 library.
64  * \{
65  */
66 
67 /*!
68  * \brief Sanity test Xbox interface.
69  *
70  * \return Returns 0 if test succeeds, else returns \h_lt 0.
71  */
72 static int testXboxSanity()
73 {
74  HIDXbox360 *pXbox;
75  int rc;
76 
77  // manually set rnr log level
78  LOG_SET_THRESHOLD(LOG_LEVEL_DIAG3);
79 
81 
82  if( (rc = pXbox->open()) < 0 )
83  {
84  LOGERROR("Failed to open Xbox360 controller.");
85  }
86 
87  else if( !pXbox->ping() )
88  {
89  LOGERROR("Failed to ping Xbox360 controller.");
90  rc = -1;
91  }
92 
93  else
94  {
95  rc = 0;
96  }
97 
98  if( pXbox->isConnected() )
99  {
100  pXbox->close();
101  }
102 
103  delete pXbox;
104 
105  return rc;
106 }
107 
108 /*!
109  * \brief Test Xbox input interface.
110  *
111  * \return Returns 0 if test succeeds, else returns \h_lt 0.
112  */
113 static int testXboxInput()
114 {
115  int bttnSuccess = HIDInput::MNEM_START;
116  int bttnFail = bttnSuccess + 1;
117  int rc;
118 
119  // manually set rnr log level
120  LOG_SET_THRESHOLD(LOG_LEVEL_DIAG3);
121 
123 
124  if( (rc = xbox.open()) < 0 )
125  {
126  LOGERROR("Failed to open Xbox360 controller.");
127  return -1;
128  }
129 
130  xbox.assocFeature(Xbox360FeatIdXButton, bttnSuccess);
131  xbox.assocFeature(Xbox360FeatIdYButton, bttnFail);
132 
133  fprintf(stderr,
134  "\nTesting Xbox360 Input Interface.\n"
135  " Press the Xbox 'X' button to terminate test with success.\n"
136  " Press the Xbox 'Y' button to terminate test with failure.\n\n");
137 
138  xbox.debugPrintHdr();
139 
140  while( true )
141  {
142  if( (rc = xbox.update()) < 0 )
143  {
144  LOGERROR("Failed to update Xbox360 controller state.");
145  break;
146  }
147 
148  xbox.debugPrintState();
149 
150  if( xbox.getFeatureVal(bttnSuccess) == HID_BTTN_DOWN )
151  {
152  rc = 0;
153  break;
154  }
155  else if( xbox.getFeatureVal(bttnFail) == HID_BTTN_DOWN )
156  {
157  rc = -1;
158  break;
159  }
160  }
161 
162  fprintf(stderr, "\n\n");
163 
164  return rc;
165 }
166 
167 /*!
168  * \brief Tactically test Xbox rumble interface.
169  *
170  * \return Returns 0 if test succeeds, else returns \h_lt 0.
171  */
172 static int testXboxRumble()
173 {
174  int bttnSuccess = HIDInput::MNEM_START;
175  int bttnFail = bttnSuccess + 1;
176  int nLeftTrigger = 0;
177  int nRightTrigger = 0;
178  int nLeftRumble = 0;
179  int nRightRumble = 0;
180  int rc;
181 
182  // manually set rnr log level
183  LOG_SET_THRESHOLD(LOG_LEVEL_DIAG3);
184 
186 
187  if( (rc = xbox.open()) < 0 )
188  {
189  LOGERROR("Failed to open Xbox360 controller.");
190  return -1;
191  }
192 
193  xbox.assocFeature(Xbox360FeatIdXButton, bttnSuccess);
194  xbox.assocFeature(Xbox360FeatIdYButton, bttnFail);
195 
196  fprintf(stderr,
197  "\nTesting Xbox360 Rumble Interface.\n"
198  " Squeeze left (right) trigger for left (right) rumble motor.\n"
199  " Press the Xbox 'X' button to terminate test with success.\n"
200  " Press the Xbox 'Y' button to terminate test with failure.\n\n");
201 
202  xbox.debugPrintHdr();
203 
204  while( true )
205  {
206  if( (rc = xbox.update()) < 0 )
207  {
208  LOGERROR("Failed to update Xbox360 controller state.");
209  break;
210  }
211 
212  xbox.debugPrintState();
213 
214  if( xbox.getFeatureVal(bttnSuccess) == HID_BTTN_DOWN )
215  {
216  rc = 0;
217  break;
218  }
219  else if( xbox.getFeatureVal(bttnFail) == HID_BTTN_DOWN )
220  {
221  rc = -1;
222  break;
223  }
224  else
225  {
226  nLeftTrigger = xbox.getFeatureVal(Xbox360FeatIdLeftTrigger);
227  nRightTrigger = xbox.getFeatureVal(Xbox360FeatIdRightTrigger);
228  nLeftRumble = xbox.getFeatureVal(Xbox360FeatIdLeftRumble);
229  nRightRumble = xbox.getFeatureVal(Xbox360FeatIdRightRumble);
230 
231  if( (nLeftTrigger != nLeftRumble) || (nRightTrigger != nRightRumble) )
232  {
233  xbox.setRumble(nLeftTrigger, nRightTrigger);
234  }
235  }
236  }
237 
238  fprintf(stderr, "\n\n");
239 
240  return rc;
241 }
242 
243 /*!
244  * \brief Visually test Xbox LED interface.
245  *
246  * \return Returns 0 if test succeeds, else returns \h_lt 0.
247  */
248 static int testXboxLED()
249 {
250  int bttnSuccess = HIDInput::MNEM_START;
251  int bttnFail = bttnSuccess + 1;
252  int nLeftBump = 0;
253  int nRightBump = 0;
254  int nPattern = 0;
255  int rc;
256 
257  // manually set rnr log level
258  LOG_SET_THRESHOLD(LOG_LEVEL_DIAG3);
259 
261 
262  if( (rc = xbox.open()) < 0 )
263  {
264  LOGERROR("Failed to open Xbox360 controller.");
265  return -1;
266  }
267 
268  xbox.assocFeature(Xbox360FeatIdXButton, bttnSuccess);
269  xbox.assocFeature(Xbox360FeatIdYButton, bttnFail);
270 
271  fprintf(stderr,
272  "\nTesting Xbox360 LED Interface.\n"
273  " Press left (right) bumper to increment (decrement) the LED pattern.\n"
274  " Press the Xbox 'X' button to terminate test with success.\n"
275  " Press the Xbox 'Y' button to terminate test with failure.\n\n");
276 
277  xbox.debugPrintHdr();
278 
279  while( true )
280  {
281  if( (rc = xbox.update()) < 0 )
282  {
283  LOGERROR("Failed to update Xbox360 controller state.");
284  break;
285  }
286 
287  xbox.debugPrintState();
288 
289  if( xbox.getFeatureVal(bttnSuccess) == HID_BTTN_DOWN )
290  {
291  rc = 0;
292  break;
293  }
294  else if( xbox.getFeatureVal(bttnFail) == HID_BTTN_DOWN )
295  {
296  rc = -1;
297  break;
298  }
299  else if( nLeftBump != xbox.getFeatureVal(Xbox360FeatIdLeftBump) )
300  {
301  nLeftBump = xbox.getFeatureVal(Xbox360FeatIdLeftBump);
302 
303  if( nLeftBump )
304  {
305  nPattern = (nPattern + 1) % XBOX360_LED_PAT_NUMOF;
306  xbox.setLED(nPattern);
307  }
308  }
309  else if( nRightBump != xbox.getFeatureVal(Xbox360FeatIdRightBump) )
310  {
311  nRightBump = xbox.getFeatureVal(Xbox360FeatIdRightBump);
312 
313  if( nRightBump )
314  {
315  nPattern = (nPattern-1 + XBOX360_LED_PAT_NUMOF)%XBOX360_LED_PAT_NUMOF;
316  xbox.setLED(nPattern);
317  }
318  }
319  }
320 
321  fprintf(stderr, "\n\n");
322 
323  return rc;
324 }
325 
326 #ifndef JENKINS
327 
328 /*!
329  * \brief Sanity test Xbox360 controller interface.
330  *
331  * \par The Test:
332  * Construct HIDXbox360 object.\n
333  * Open.\n
334  * Ping.\n
335  * Close.\n
336  * Destroy HIDXbox360 object.
337  */
338 TEST(Xbox360, XboxSanity)
339 {
340  EXPECT_TRUE( testXboxSanity() == 0 );
341 }
342 
343 
344 /*!
345  * \brief Visually test Xbox360 controller input interface.
346  *
347  * \par The Test:
348  * Construct HIDXbox360 object.\n
349  * Open.\n
350  * User interaction.\n
351  * Close.\n
352  * Destroy HIDXbox360 object.
353  */
354 TEST(Xbox360, XboxInput)
355 {
356  EXPECT_TRUE( testXboxInput() == 0 );
357 }
358 
359 /*!
360  * \brief Tactually test Xbox360 controller rumble interface.
361  *
362  * \par The Test:
363  * Construct HIDXbox360 object.\n
364  * Open.\n
365  * User interaction.\n
366  * Close.\n
367  * Destroy HIDXbox360 object.
368  */
369 TEST(Xbox360, XboxRumble)
370 {
371  EXPECT_TRUE( testXboxRumble() == 0 );
372 }
373 
374 /*!
375  * \brief Visually test Xbox360 controller LED interface.
376  *
377  * \par The Test:
378  * Construct HIDXbox360 object.\n
379  * Open.\n
380  * User interaction.\n
381  * Close.\n
382  * Destroy HIDXbox360 object.
383  */
384 TEST(Xbox360, XboxLED)
385 {
386  EXPECT_TRUE( testXboxLED() == 0 );
387 }
388 
389 #endif // JENKINS
390 
391 
392 /*!
393  * \}
394  */
virtual int close()
Close connection to an opened USB Xbox360 controller.
Definition: HIDXbox360.cxx:230
virtual int open()
Open connection to an USB Xbox360 controller.
Definition: HIDXbox360.cxx:159
void debugPrintState()
Simple debug print state.
Xbox360 Controller C interface.
static const int MNEM_START
user mapped mnemonic starting index
Definition: HID.h:103
virtual bool ping()
Ping device if it is connected and is responding.
Definition: HIDXbox360.cxx:414
right trigger [0-255]
Definition: HIDXbox360.h:635
Common Human Interface Device Interface.
static int testXboxRumble()
Tactically test Xbox rumble interface.
void debugPrintHdr()
Simple debug print header.
Y button [0,1].
Definition: HIDXbox360.h:633
int setRumble(int nLeftMot, int nRightMot)
Set the rumble instensity.
Definition: HIDXbox360.cxx:492
#define HID_BTTN_DOWN
button/key state is down or pressed
Definition: HID.h:53
right hi-freq rumble motor [0-255]
Definition: HIDXbox360.h:641
virtual int getFeatureVal(int iMnem)
Get the value associated with the mapped user mnemonic.
Definition: HIDXbox360.h:720
Xbox360 controller HID input class.
Definition: HIDXbox360.h:651
virtual bool isConnected()
Query if HID is connected.
Definition: HID.h:167
virtual int update(uint_t uMSec=T_UPDATE_DFT)
Read device and update HID state.
virtual int assocFeature(int iFeatId, int iMnem)
Associate user mnemonic to the device feature (e.g. button) id.
Definition: HID.h:184
int setLED(int nPattern)
Set the LED pattern.
Definition: HIDXbox360.cxx:623
left bump (left shoulder) [0,1]
Definition: HIDXbox360.h:627
static int testXboxInput()
Test Xbox input interface.
static int testXboxLED()
Visually test Xbox LED interface.
#define XBOX_LIBUSB_DEBUG_WARN
log libusb warnings and errors
Definition: HIDXbox360.h:243
left low-freq rumble motor [0-255]
Definition: HIDXbox360.h:640
right bump (right shoulder) [0,1]
Definition: HIDXbox360.h:628
#define XBOX360_LED_PAT_NUMOF
number of patterns
Definition: HIDXbox360.h:586
static int testXboxSanity()
Sanity test Xbox interface.
RoadNarrows Robotics standard namespace.
Definition: HID.h:65
X button [0,1].
Definition: HIDXbox360.h:632
left trigger [0-255]
Definition: HIDXbox360.h:634
TEST(Xbox360, XboxSanity)
Sanity test Xbox360 controller interface.