diff --git a/_x_b_o_x_o_n_e_8cpp_source.html b/_x_b_o_x_o_n_e_8cpp_source.html index 39fc09c7..0305a52b 100644 --- a/_x_b_o_x_o_n_e_8cpp_source.html +++ b/_x_b_o_x_o_n_e_8cpp_source.html @@ -63,7 +63,7 @@ $(function() {
XBOXONE.cpp
-Go to the documentation of this file.
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2  Copyright (C) 2015 guruthree
3 
4  This software may be distributed and modified under the terms of the GNU
5  General Public License version 2 (GPL2) as published by the Free Software
6  Foundation and appearing in the file GPL2.TXT included in the packaging of
7  this file. Please note that GPL2 Section 2[b] requires that all works based
8  on this software must also be made publicly available under the terms of
9  the GPL2 ("Copyleft").
10 
11  Contact information
12  -------------------
13 
14  Kristian Lauszus, TKJ Electronics
15  Web : http://www.tkjelectronics.com
16  e-mail : kristianl@tkjelectronics.com
17 
18  guruthree
19  Web : https://github.com/guruthree/
20  */
21 
22 #include "XBOXONE.h"
23 // To enable serial debugging see "settings.h"
24 //#define EXTRADEBUG // Uncomment to get even more debugging data
25 //#define PRINTREPORT // Uncomment to print the report send by the Xbox ONE Controller
26 
28 pUsb(p), // pointer to USB class instance - mandatory
29 bAddress(0), // device address - mandatory
30 bNumEP(1), // If config descriptor needs to be parsed
31 qNextPollTime(0), // Reset NextPollTime
32 pollInterval(0),
33 bPollEnable(false) { // don't start polling before dongle is connected
34  for(uint8_t i = 0; i < XBOX_ONE_MAX_ENDPOINTS; i++) {
35  epInfo[i].epAddr = 0;
36  epInfo[i].maxPktSize = (i) ? 0 : 8;
37  epInfo[i].bmSndToggle = 0;
38  epInfo[i].bmRcvToggle = 0;
40  }
41 
42  if(pUsb) // register in USB subsystem
43  pUsb->RegisterDeviceClass(this); //set devConfig[] entry
44 }
45 
46 uint8_t XBOXONE::Init(uint8_t parent, uint8_t port, bool lowspeed) {
47  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
48  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
49  uint8_t rcode;
50  UsbDevice *p = NULL;
51  EpInfo *oldep_ptr = NULL;
52  uint16_t PID, VID;
53  uint8_t num_of_conf; // Number of configurations
54 
55  // get memory address of USB device address pool
56  AddressPool &addrPool = pUsb->GetAddressPool();
57 #ifdef EXTRADEBUG
58  Notify(PSTR("\r\nXBOXONE Init"), 0x80);
59 #endif
60  // check if address has already been assigned to an instance
61  if(bAddress) {
62 #ifdef DEBUG_USB_HOST
63  Notify(PSTR("\r\nAddress in use"), 0x80);
64 #endif
66  }
67 
68  // Get pointer to pseudo device with address 0 assigned
69  p = addrPool.GetUsbDevicePtr(0);
70 
71  if(!p) {
72 #ifdef DEBUG_USB_HOST
73  Notify(PSTR("\r\nAddress not found"), 0x80);
74 #endif
76  }
77 
78  if(!p->epinfo) {
79 #ifdef DEBUG_USB_HOST
80  Notify(PSTR("\r\nepinfo is null"), 0x80);
81 #endif
83  }
84 
85  // Save old pointer to EP_RECORD of address 0
86  oldep_ptr = p->epinfo;
87 
88  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
89  p->epinfo = epInfo;
90 
91  p->lowspeed = lowspeed;
92 
93  // Get device descriptor
94  rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
95  // Restore p->epinfo
96  p->epinfo = oldep_ptr;
97 
98  if(rcode)
99  goto FailGetDevDescr;
100 
101  VID = udd->idVendor;
102  PID = udd->idProduct;
103 
104  if(!VIDPIDOK(VID, PID)) // Check VID
105  goto FailUnknownDevice;
106 
107  // Allocate new address according to device class
108  bAddress = addrPool.AllocAddress(parent, false, port);
109 
110  if(!bAddress)
112 
113  // Extract Max Packet Size from device descriptor
114  epInfo[0].maxPktSize = udd->bMaxPacketSize0;
115 
116  // Assign new address to the device
117  rcode = pUsb->setAddr(0, 0, bAddress);
118  if(rcode) {
119  p->lowspeed = false;
120  addrPool.FreeAddress(bAddress);
121  bAddress = 0;
122 #ifdef DEBUG_USB_HOST
123  Notify(PSTR("\r\nsetAddr: "), 0x80);
124  D_PrintHex<uint8_t > (rcode, 0x80);
125 #endif
126  return rcode;
127  }
128 #ifdef EXTRADEBUG
129  Notify(PSTR("\r\nAddr: "), 0x80);
130  D_PrintHex<uint8_t > (bAddress, 0x80);
131 #endif
132  //delay(300); // Spec says you should wait at least 200ms
133 
134  p->lowspeed = false;
135 
136  //get pointer to assigned address record
137  p = addrPool.GetUsbDevicePtr(bAddress);
138  if(!p)
140 
141  p->lowspeed = lowspeed;
142 
143  // Assign epInfo to epinfo pointer - only EP0 is known
144  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
145  if(rcode)
146  goto FailSetDevTblEntry;
147 
148  num_of_conf = udd->bNumConfigurations; // Number of configurations
149 
150  USBTRACE2("NC:", num_of_conf);
151 
152  // Check if attached device is a Xbox One controller and fill endpoint data structure
153  for(uint8_t i = 0; i < num_of_conf; i++) {
154  ConfigDescParser<0, 0, 0, 0> confDescrParser(this); // Allow all devices, as we have already verified that it is a Xbox One controller from the VID and PID
155  rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
156  if(rcode) // Check error code
157  goto FailGetConfDescr;
158  if(bNumEP >= XBOX_ONE_MAX_ENDPOINTS) // All endpoints extracted
159  break;
160  }
161 
163  goto FailUnknownDevice;
164 
165  rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
166  if(rcode)
167  goto FailSetDevTblEntry;
168 
169  delay(200); // Give time for address change
170 
171  rcode = pUsb->setConf(bAddress, epInfo[ XBOX_ONE_CONTROL_PIPE ].epAddr, bConfNum);
172  if(rcode)
173  goto FailSetConfDescr;
174 
175 #ifdef DEBUG_USB_HOST
176  Notify(PSTR("\r\nXbox One Controller Connected\r\n"), 0x80);
177 #endif
178 
179  delay(200); // let things settle
180 
181  // Initialize the controller for input
182  cmdCounter = 0; // Reset the counter used when sending out the commands
183  uint8_t writeBuf[5];
184  writeBuf[0] = 0x05;
185  writeBuf[1] = 0x20;
186  // Byte 2 is set in "XboxCommand"
187  writeBuf[3] = 0x01;
188  writeBuf[4] = 0x00;
189  rcode = XboxCommand(writeBuf, 5);
190  if (rcode)
191  goto Fail;
192 
193  onInit();
194  XboxOneConnected = true;
195  bPollEnable = true;
196  return 0; // Successful configuration
197 
198  /* Diagnostic messages */
199 FailGetDevDescr:
200 #ifdef DEBUG_USB_HOST
202  goto Fail;
203 #endif
204 
205 FailSetDevTblEntry:
206 #ifdef DEBUG_USB_HOST
208  goto Fail;
209 #endif
210 
211 FailGetConfDescr:
212 #ifdef DEBUG_USB_HOST
214  goto Fail;
215 #endif
216 
217 FailSetConfDescr:
218 #ifdef DEBUG_USB_HOST
220 #endif
221  goto Fail;
222 
223 FailUnknownDevice:
224 #ifdef DEBUG_USB_HOST
225  NotifyFailUnknownDevice(VID, PID);
226 #endif
228 
229 Fail:
230 #ifdef DEBUG_USB_HOST
231  Notify(PSTR("\r\nXbox One Init Failed, error code: "), 0x80);
232  NotifyFail(rcode);
233 #endif
234  Release();
235  return rcode;
236 }
237 
238 /* Extracts endpoint information from config descriptor */
239 void XBOXONE::EndpointXtract(uint8_t conf,
240  uint8_t iface __attribute__((unused)),
241  uint8_t alt __attribute__((unused)),
242  uint8_t proto __attribute__((unused)),
243  const USB_ENDPOINT_DESCRIPTOR *pep)
244 {
245 
246  bConfNum = conf;
247  uint8_t index;
248 
249  if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT) { // Interrupt endpoint
250  index = (pep->bEndpointAddress & 0x80) == 0x80 ? XBOX_ONE_INPUT_PIPE : XBOX_ONE_OUTPUT_PIPE; // Set the endpoint index
251  } else
252  return;
253 
254  // Fill the rest of endpoint data structure
255  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
256  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
257 #ifdef EXTRADEBUG
259 #endif
260  if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
261  pollInterval = pep->bInterval;
262  bNumEP++;
263 }
264 
266  __attribute__((unused)))
267 {
268 #ifdef EXTRADEBUG
269  Notify(PSTR("\r\nEndpoint descriptor:"), 0x80);
270  Notify(PSTR("\r\nLength:\t\t"), 0x80);
271  D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
272  Notify(PSTR("\r\nType:\t\t"), 0x80);
273  D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
274  Notify(PSTR("\r\nAddress:\t"), 0x80);
275  D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
276  Notify(PSTR("\r\nAttributes:\t"), 0x80);
277  D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
278  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
279  D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
280  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
281  D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
282 #endif
283 }
284 
285 /* Performs a cleanup after failed Init() attempt */
286 uint8_t XBOXONE::Release() {
287  XboxOneConnected = false;
289  bAddress = 0; // Clear device address
290  bNumEP = 1; // Must have to be reset to 1
291  qNextPollTime = 0; // Reset next poll time
292  pollInterval = 0;
293  bPollEnable = false;
294 #ifdef DEBUG_USB_HOST
295  Notify(PSTR("\r\nXbox One Controller Disconnected\r\n"), 0x80);
296 #endif
297  return 0;
298 }
299 
300 uint8_t XBOXONE::Poll() {
301  uint8_t rcode = 0;
302 
303  if(!bPollEnable)
304  return 0;
305 
306  if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { // Do not poll if shorter than polling interval
307  qNextPollTime = (uint32_t)millis() + pollInterval; // Set new poll time
308  uint16_t length = (uint16_t)epInfo[ XBOX_ONE_INPUT_PIPE ].maxPktSize; // Read the maximum packet size from the endpoint
309  uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ XBOX_ONE_INPUT_PIPE ].epAddr, &length, readBuf, pollInterval);
310  if(!rcode) {
311  readReport();
312 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller
313  for(uint8_t i = 0; i < length; i++) {
314  D_PrintHex<uint8_t > (readBuf[i], 0x80);
315  Notify(PSTR(" "), 0x80);
316  }
317  Notify(PSTR("\r\n"), 0x80);
318 #endif
319  }
320 #ifdef DEBUG_USB_HOST
321  else if(rcode != hrNAK) { // Not a matter of no update to send
322  Notify(PSTR("\r\nXbox One Poll Failed, error code: "), 0x80);
323  NotifyFail(rcode);
324  }
325 #endif
326  }
327  return rcode;
328 }
329 
330 void XBOXONE::readReport() {
331  if(readBuf[0] == 0x07) {
332  // The XBOX button has a separate message
333  if(readBuf[4] == 1)
334  ButtonState |= pgm_read_word(&XBOX_BUTTONS[XBOX]);
335  else
336  ButtonState &= ~pgm_read_word(&XBOX_BUTTONS[XBOX]);
337 
338  if(ButtonState != OldButtonState) {
339  ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
340  OldButtonState = ButtonState;
341  }
342  }
343  if(readBuf[0] != 0x20) { // Check if it's the correct report, otherwise return - the controller also sends different status reports
344 #ifdef EXTRADEBUG
345  Notify(PSTR("\r\nXbox Poll: "), 0x80);
346  D_PrintHex<uint8_t > (readBuf[0], 0x80); // 0x03 is a heart beat report!
347 #endif
348  return;
349  }
350 
351  uint16_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[XBOX]); // Since the XBOX button is separate, save it and add it back in
352  // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons
353  ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4);
354 
355  triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);
356  triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);
357 
358  hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
359  hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
360  hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);
361  hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);
362 
363  //Notify(PSTR("\r\nButtonState"), 0x80);
364  //PrintHex<uint16_t>(ButtonState, 0x80);
365 
366  if(ButtonState != OldButtonState) {
367  ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
368  OldButtonState = ButtonState;
369  }
370 
371  // Handle click detection for triggers
372  if(triggerValue[0] != 0 && triggerValueOld[0] == 0)
373  L2Clicked = true;
374  triggerValueOld[0] = triggerValue[0];
375  if(triggerValue[1] != 0 && triggerValueOld[1] == 0)
376  R2Clicked = true;
377  triggerValueOld[1] = triggerValue[1];
378 }
379 
381  if(b == L2) // These are analog buttons
382  return triggerValue[0];
383  else if(b == R2)
384  return triggerValue[1];
385  return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b])));
386 }
387 
389  if(b == L2) {
390  if(L2Clicked) {
391  L2Clicked = false;
392  return true;
393  }
394  return false;
395  } else if(b == R2) {
396  if(R2Clicked) {
397  R2Clicked = false;
398  return true;
399  }
400  return false;
401  }
402  uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);
403  bool click = (ButtonClickState & button);
404  ButtonClickState &= ~button; // Clear "click" event
405  return click;
406 }
407 
409  return hatValue[a];
410 }
411 
412 /* Xbox Controller commands */
413 uint8_t XBOXONE::XboxCommand(uint8_t* data, uint16_t nbytes) {
414  data[2] = cmdCounter++; // Increment the output command counter
415  uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ XBOX_ONE_OUTPUT_PIPE ].epAddr, nbytes, data);
416 #ifdef DEBUG_USB_HOST
417  Notify(PSTR("\r\nXboxCommand, Return: "), 0x80);
418  D_PrintHex<uint8_t > (rcode, 0x80);
419 #endif
420  return rcode;
421 }
422 
423 // The Xbox One packets are described at: https://github.com/quantus/xbox-one-controller-protocol
424 void XBOXONE::onInit() {
425  // A short buzz to show the controller is active
426  uint8_t writeBuf[13];
427 
428  // Activate rumble
429  writeBuf[0] = 0x09;
430  writeBuf[1] = 0x00;
431  // Byte 2 is set in "XboxCommand"
432 
433  // Single rumble effect
434  writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)
435  writeBuf[4] = 0x00; // Mode
436  writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)
437  writeBuf[6] = 0x04; // lT force
438  writeBuf[7] = 0x04; // rT force
439  writeBuf[8] = 0x20; // L force
440  writeBuf[9] = 0x20; // R force
441  writeBuf[10] = 0x80; // Length of pulse
442  writeBuf[11] = 0x00; // Off period
443  writeBuf[12] = 0x00; // Repeat count
444  XboxCommand(writeBuf, 13);
445 
446  if(pFuncOnInit)
447  pFuncOnInit(); // Call the user function
448 }
449 
451  uint8_t writeBuf[13];
452 
453  // Activate rumble
454  writeBuf[0] = 0x09;
455  writeBuf[1] = 0x00;
456  // Byte 2 is set in "XboxCommand"
457 
458  // Continuous rumble effect
459  writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)
460  writeBuf[4] = 0x00; // Mode
461  writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)
462  writeBuf[6] = 0x00; // lT force
463  writeBuf[7] = 0x00; // rT force
464  writeBuf[8] = 0x00; // L force
465  writeBuf[9] = 0x00; // R force
466  writeBuf[10] = 0x00; // On period
467  writeBuf[11] = 0x00; // Off period
468  writeBuf[12] = 0x00; // Repeat count
469  XboxCommand(writeBuf, 13);
470 }
471 
472 void XBOXONE::setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor) {
473  uint8_t writeBuf[13];
474 
475  // Activate rumble
476  writeBuf[0] = 0x09;
477  writeBuf[1] = 0x00;
478  // Byte 2 is set in "XboxCommand"
479 
480  // Continuous rumble effect
481  writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)
482  writeBuf[4] = 0x00; // Mode
483  writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)
484  writeBuf[6] = leftTrigger; // lT force
485  writeBuf[7] = rightTrigger; // rT force
486  writeBuf[8] = leftMotor; // L force
487  writeBuf[9] = rightMotor; // R force
488  writeBuf[10] = 0xFF; // On period
489  writeBuf[11] = 0x00; // Off period
490  writeBuf[12] = 0xFF; // Repeat count
491  XboxCommand(writeBuf, 13);
492 }
uint8_t bConfNum
Definition: XBOXONE.h:186
+Go to the documentation of this file.
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2  Copyright (C) 2015 guruthree
3 
4  This software may be distributed and modified under the terms of the GNU
5  General Public License version 2 (GPL2) as published by the Free Software
6  Foundation and appearing in the file GPL2.TXT included in the packaging of
7  this file. Please note that GPL2 Section 2[b] requires that all works based
8  on this software must also be made publicly available under the terms of
9  the GPL2 ("Copyleft").
10 
11  Contact information
12  -------------------
13 
14  Kristian Lauszus, TKJ Electronics
15  Web : http://www.tkjelectronics.com
16  e-mail : kristianl@tkjelectronics.com
17 
18  guruthree
19  Web : https://github.com/guruthree/
20  */
21 
22 #include "XBOXONE.h"
23 // To enable serial debugging see "settings.h"
24 //#define EXTRADEBUG // Uncomment to get even more debugging data
25 //#define PRINTREPORT // Uncomment to print the report send by the Xbox ONE Controller
26 
28 pUsb(p), // pointer to USB class instance - mandatory
29 bAddress(0), // device address - mandatory
30 bNumEP(1), // If config descriptor needs to be parsed
31 qNextPollTime(0), // Reset NextPollTime
32 pollInterval(0),
33 bPollEnable(false) { // don't start polling before dongle is connected
34  for(uint8_t i = 0; i < XBOX_ONE_MAX_ENDPOINTS; i++) {
35  epInfo[i].epAddr = 0;
36  epInfo[i].maxPktSize = (i) ? 0 : 8;
37  epInfo[i].bmSndToggle = 0;
38  epInfo[i].bmRcvToggle = 0;
40  }
41 
42  if(pUsb) // register in USB subsystem
43  pUsb->RegisterDeviceClass(this); //set devConfig[] entry
44 }
45 
46 uint8_t XBOXONE::Init(uint8_t parent, uint8_t port, bool lowspeed) {
47  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
48  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
49  uint8_t rcode;
50  UsbDevice *p = NULL;
51  EpInfo *oldep_ptr = NULL;
52  uint16_t PID, VID;
53  uint8_t num_of_conf; // Number of configurations
54 
55  // get memory address of USB device address pool
56  AddressPool &addrPool = pUsb->GetAddressPool();
57 #ifdef EXTRADEBUG
58  Notify(PSTR("\r\nXBOXONE Init"), 0x80);
59 #endif
60  // check if address has already been assigned to an instance
61  if(bAddress) {
62 #ifdef DEBUG_USB_HOST
63  Notify(PSTR("\r\nAddress in use"), 0x80);
64 #endif
66  }
67 
68  // Get pointer to pseudo device with address 0 assigned
69  p = addrPool.GetUsbDevicePtr(0);
70 
71  if(!p) {
72 #ifdef DEBUG_USB_HOST
73  Notify(PSTR("\r\nAddress not found"), 0x80);
74 #endif
76  }
77 
78  if(!p->epinfo) {
79 #ifdef DEBUG_USB_HOST
80  Notify(PSTR("\r\nepinfo is null"), 0x80);
81 #endif
83  }
84 
85  // Save old pointer to EP_RECORD of address 0
86  oldep_ptr = p->epinfo;
87 
88  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
89  p->epinfo = epInfo;
90 
91  p->lowspeed = lowspeed;
92 
93  // Get device descriptor
94  rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
95  // Restore p->epinfo
96  p->epinfo = oldep_ptr;
97 
98  if(rcode)
99  goto FailGetDevDescr;
100 
101  VID = udd->idVendor;
102  PID = udd->idProduct;
103 
104  if(!VIDPIDOK(VID, PID)) // Check VID
105  goto FailUnknownDevice;
106 
107  // Allocate new address according to device class
108  bAddress = addrPool.AllocAddress(parent, false, port);
109 
110  if(!bAddress)
112 
113  // Extract Max Packet Size from device descriptor
114  epInfo[0].maxPktSize = udd->bMaxPacketSize0;
115 
116  // Assign new address to the device
117  rcode = pUsb->setAddr(0, 0, bAddress);
118  if(rcode) {
119  p->lowspeed = false;
120  addrPool.FreeAddress(bAddress);
121  bAddress = 0;
122 #ifdef DEBUG_USB_HOST
123  Notify(PSTR("\r\nsetAddr: "), 0x80);
124  D_PrintHex<uint8_t > (rcode, 0x80);
125 #endif
126  return rcode;
127  }
128 #ifdef EXTRADEBUG
129  Notify(PSTR("\r\nAddr: "), 0x80);
130  D_PrintHex<uint8_t > (bAddress, 0x80);
131 #endif
132  //delay(300); // Spec says you should wait at least 200ms
133 
134  p->lowspeed = false;
135 
136  //get pointer to assigned address record
137  p = addrPool.GetUsbDevicePtr(bAddress);
138  if(!p)
140 
141  p->lowspeed = lowspeed;
142 
143  // Assign epInfo to epinfo pointer - only EP0 is known
144  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
145  if(rcode)
146  goto FailSetDevTblEntry;
147 
148  num_of_conf = udd->bNumConfigurations; // Number of configurations
149 
150  USBTRACE2("NC:", num_of_conf);
151 
152  // Check if attached device is a Xbox One controller and fill endpoint data structure
153  for(uint8_t i = 0; i < num_of_conf; i++) {
154  ConfigDescParser<0, 0, 0, 0> confDescrParser(this); // Allow all devices, as we have already verified that it is a Xbox One controller from the VID and PID
155  rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
156  if(rcode) // Check error code
157  goto FailGetConfDescr;
158  if(bNumEP >= XBOX_ONE_MAX_ENDPOINTS) // All endpoints extracted
159  break;
160  }
161 
163  goto FailUnknownDevice;
164 
165  rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
166  if(rcode)
167  goto FailSetDevTblEntry;
168 
169  delay(200); // Give time for address change
170 
171  rcode = pUsb->setConf(bAddress, epInfo[ XBOX_ONE_CONTROL_PIPE ].epAddr, bConfNum);
172  if(rcode)
173  goto FailSetConfDescr;
174 
175 #ifdef DEBUG_USB_HOST
176  Notify(PSTR("\r\nXbox One Controller Connected\r\n"), 0x80);
177 #endif
178 
179  delay(200); // let things settle
180 
181  // Initialize the controller for input
182  cmdCounter = 0; // Reset the counter used when sending out the commands
183  uint8_t writeBuf[5];
184  writeBuf[0] = 0x05;
185  writeBuf[1] = 0x20;
186  // Byte 2 is set in "XboxCommand"
187  writeBuf[3] = 0x01;
188  writeBuf[4] = 0x00;
189  rcode = XboxCommand(writeBuf, 5);
190  if (rcode)
191  goto Fail;
192 
193  onInit();
194  XboxOneConnected = true;
195  bPollEnable = true;
196  return 0; // Successful configuration
197 
198  /* Diagnostic messages */
199 FailGetDevDescr:
200 #ifdef DEBUG_USB_HOST
202  goto Fail;
203 #endif
204 
205 FailSetDevTblEntry:
206 #ifdef DEBUG_USB_HOST
208  goto Fail;
209 #endif
210 
211 FailGetConfDescr:
212 #ifdef DEBUG_USB_HOST
214  goto Fail;
215 #endif
216 
217 FailSetConfDescr:
218 #ifdef DEBUG_USB_HOST
220 #endif
221  goto Fail;
222 
223 FailUnknownDevice:
224 #ifdef DEBUG_USB_HOST
225  NotifyFailUnknownDevice(VID, PID);
226 #endif
228 
229 Fail:
230 #ifdef DEBUG_USB_HOST
231  Notify(PSTR("\r\nXbox One Init Failed, error code: "), 0x80);
232  NotifyFail(rcode);
233 #endif
234  Release();
235  return rcode;
236 }
237 
238 /* Extracts endpoint information from config descriptor */
239 void XBOXONE::EndpointXtract(uint8_t conf,
240  uint8_t iface __attribute__((unused)),
241  uint8_t alt __attribute__((unused)),
242  uint8_t proto __attribute__((unused)),
243  const USB_ENDPOINT_DESCRIPTOR *pep)
244 {
245 
246  bConfNum = conf;
247  uint8_t index;
248 
249  if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT) { // Interrupt endpoint
250  index = (pep->bEndpointAddress & 0x80) == 0x80 ? XBOX_ONE_INPUT_PIPE : XBOX_ONE_OUTPUT_PIPE; // Set the endpoint index
251  } else
252  return;
253 
254  // Fill the rest of endpoint data structure
255  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
256  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
257 #ifdef EXTRADEBUG
259 #endif
260  if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
261  pollInterval = pep->bInterval;
262  bNumEP++;
263 }
264 
266  __attribute__((unused)))
267 {
268 #ifdef EXTRADEBUG
269  Notify(PSTR("\r\nEndpoint descriptor:"), 0x80);
270  Notify(PSTR("\r\nLength:\t\t"), 0x80);
271  D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
272  Notify(PSTR("\r\nType:\t\t"), 0x80);
273  D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
274  Notify(PSTR("\r\nAddress:\t"), 0x80);
275  D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
276  Notify(PSTR("\r\nAttributes:\t"), 0x80);
277  D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
278  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
279  D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
280  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
281  D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
282 #endif
283 }
284 
285 /* Performs a cleanup after failed Init() attempt */
286 uint8_t XBOXONE::Release() {
287  XboxOneConnected = false;
289  bAddress = 0; // Clear device address
290  bNumEP = 1; // Must have to be reset to 1
291  qNextPollTime = 0; // Reset next poll time
292  pollInterval = 0;
293  bPollEnable = false;
294 #ifdef DEBUG_USB_HOST
295  Notify(PSTR("\r\nXbox One Controller Disconnected\r\n"), 0x80);
296 #endif
297  return 0;
298 }
299 
300 uint8_t XBOXONE::Poll() {
301  uint8_t rcode = 0;
302 
303  if(!bPollEnable)
304  return 0;
305 
306  if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { // Do not poll if shorter than polling interval
307  qNextPollTime = (uint32_t)millis() + pollInterval; // Set new poll time
308  uint16_t length = (uint16_t)epInfo[ XBOX_ONE_INPUT_PIPE ].maxPktSize; // Read the maximum packet size from the endpoint
309  uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ XBOX_ONE_INPUT_PIPE ].epAddr, &length, readBuf, pollInterval);
310  if(!rcode) {
311  readReport();
312 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller
313  for(uint8_t i = 0; i < length; i++) {
314  D_PrintHex<uint8_t > (readBuf[i], 0x80);
315  Notify(PSTR(" "), 0x80);
316  }
317  Notify(PSTR("\r\n"), 0x80);
318 #endif
319  }
320 #ifdef DEBUG_USB_HOST
321  else if(rcode != hrNAK) { // Not a matter of no update to send
322  Notify(PSTR("\r\nXbox One Poll Failed, error code: "), 0x80);
323  NotifyFail(rcode);
324  }
325 #endif
326  }
327  return rcode;
328 }
329 
330 void XBOXONE::readReport() {
331  if(readBuf[0] == 0x07) {
332  // The XBOX button has a separate message
333  if(readBuf[4] == 1)
334  ButtonState |= pgm_read_word(&XBOX_BUTTONS[XBOX]);
335  else
336  ButtonState &= ~pgm_read_word(&XBOX_BUTTONS[XBOX]);
337 
338  if(ButtonState != OldButtonState) {
339  ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
340  OldButtonState = ButtonState;
341  }
342  }
343  if(readBuf[0] != 0x20) { // Check if it's the correct report, otherwise return - the controller also sends different status reports
344 #ifdef EXTRADEBUG
345  Notify(PSTR("\r\nXbox Poll: "), 0x80);
346  D_PrintHex<uint8_t > (readBuf[0], 0x80); // 0x03 is a heart beat report!
347 #endif
348  return;
349  }
350 
351  uint16_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[XBOX]); // Since the XBOX button is separate, save it and add it back in
352  // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons
353  ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4);
354 
355  triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);
356  triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);
357 
358  hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
359  hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
360  hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);
361  hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);
362 
363  //Notify(PSTR("\r\nButtonState"), 0x80);
364  //PrintHex<uint16_t>(ButtonState, 0x80);
365 
366  if(ButtonState != OldButtonState) {
367  ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
368  OldButtonState = ButtonState;
369  }
370 
371  // Handle click detection for triggers
372  if(triggerValue[0] != 0 && triggerValueOld[0] == 0)
373  L2Clicked = true;
374  triggerValueOld[0] = triggerValue[0];
375  if(triggerValue[1] != 0 && triggerValueOld[1] == 0)
376  R2Clicked = true;
377  triggerValueOld[1] = triggerValue[1];
378 }
379 
381  if(b == L2) // These are analog buttons
382  return triggerValue[0];
383  else if(b == R2)
384  return triggerValue[1];
385  return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b])));
386 }
387 
389  if(b == L2) {
390  if(L2Clicked) {
391  L2Clicked = false;
392  return true;
393  }
394  return false;
395  } else if(b == R2) {
396  if(R2Clicked) {
397  R2Clicked = false;
398  return true;
399  }
400  return false;
401  }
402  uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);
403  bool click = (ButtonClickState & button);
404  ButtonClickState &= ~button; // Clear "click" event
405  return click;
406 }
407 
409  return hatValue[a];
410 }
411 
412 /* Xbox Controller commands */
413 uint8_t XBOXONE::XboxCommand(uint8_t* data, uint16_t nbytes) {
414  data[2] = cmdCounter++; // Increment the output command counter
415  uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ XBOX_ONE_OUTPUT_PIPE ].epAddr, nbytes, data);
416 #ifdef DEBUG_USB_HOST
417  Notify(PSTR("\r\nXboxCommand, Return: "), 0x80);
418  D_PrintHex<uint8_t > (rcode, 0x80);
419 #endif
420  return rcode;
421 }
422 
423 // The Xbox One packets are described at: https://github.com/quantus/xbox-one-controller-protocol
424 void XBOXONE::onInit() {
425  // A short buzz to show the controller is active
426  uint8_t writeBuf[13];
427 
428  // Activate rumble
429  writeBuf[0] = 0x09;
430  writeBuf[1] = 0x00;
431  // Byte 2 is set in "XboxCommand"
432 
433  // Single rumble effect
434  writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)
435  writeBuf[4] = 0x00; // Mode
436  writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)
437  writeBuf[6] = 0x04; // lT force
438  writeBuf[7] = 0x04; // rT force
439  writeBuf[8] = 0x20; // L force
440  writeBuf[9] = 0x20; // R force
441  writeBuf[10] = 0x80; // Length of pulse
442  writeBuf[11] = 0x00; // Off period
443  writeBuf[12] = 0x00; // Repeat count
444  XboxCommand(writeBuf, 13);
445 
446  if(pFuncOnInit)
447  pFuncOnInit(); // Call the user function
448 }
449 
451  uint8_t writeBuf[13];
452 
453  // Activate rumble
454  writeBuf[0] = 0x09;
455  writeBuf[1] = 0x00;
456  // Byte 2 is set in "XboxCommand"
457 
458  // Continuous rumble effect
459  writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)
460  writeBuf[4] = 0x00; // Mode
461  writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)
462  writeBuf[6] = 0x00; // lT force
463  writeBuf[7] = 0x00; // rT force
464  writeBuf[8] = 0x00; // L force
465  writeBuf[9] = 0x00; // R force
466  writeBuf[10] = 0x00; // On period
467  writeBuf[11] = 0x00; // Off period
468  writeBuf[12] = 0x00; // Repeat count
469  XboxCommand(writeBuf, 13);
470 }
471 
472 void XBOXONE::setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor) {
473  uint8_t writeBuf[13];
474 
475  // Activate rumble
476  writeBuf[0] = 0x09;
477  writeBuf[1] = 0x00;
478  // Byte 2 is set in "XboxCommand"
479 
480  // Continuous rumble effect
481  writeBuf[3] = 0x09; // Substructure (what substructure rest of this packet has)
482  writeBuf[4] = 0x00; // Mode
483  writeBuf[5] = 0x0F; // Rumble mask (what motors are activated) (0000 lT rT L R)
484  writeBuf[6] = leftTrigger; // lT force
485  writeBuf[7] = rightTrigger; // rT force
486  writeBuf[8] = leftMotor; // L force
487  writeBuf[9] = rightMotor; // R force
488  writeBuf[10] = 0xFF; // On period
489  writeBuf[11] = 0x00; // Off period
490  writeBuf[12] = 0xFF; // Repeat count
491  XboxCommand(writeBuf, 13);
492 }
uint8_t bConfNum
Definition: XBOXONE.h:188
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:801
uint8_t bmRcvToggle
Definition: address.h:48
@@ -76,11 +76,11 @@ $(function() {
#define pgm_read_word(addr)
-
USB * pUsb
Definition: XBOXONE.h:179
+
USB * pUsb
Definition: XBOXONE.h:181
#define NotifyFail(...)
Definition: message.h:62
AnalogHatEnum
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:840
-
uint8_t bAddress
Definition: XBOXONE.h:181
+
uint8_t bAddress
Definition: XBOXONE.h:183
XBOXONE(USB *pUsb)
Definition: XBOXONE.cpp:27
#define USB_TRANSFER_TYPE_INTERRUPT
Definition: usb_ch9.h:93
#define NotifyFailGetDevDescr(...)
Definition: message.h:57
@@ -88,7 +88,7 @@ $(function() {
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: XBOXONE.cpp:239
virtual void FreeAddress(uint8_t addr)=0
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
-
uint8_t bNumEP
Definition: XBOXONE.h:188
+
uint8_t bNumEP
Definition: XBOXONE.h:190
#define Notify(...)
Definition: message.h:51
@@ -97,7 +97,7 @@ $(function() {
#define NotifyFailGetConfDescr(...)
Definition: message.h:59
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)
Definition: XBOXONE.cpp:265
uint8_t epAddr
Definition: address.h:40
-
bool XboxOneConnected
Definition: XBOXONE.h:175
+
bool XboxOneConnected
Definition: XBOXONE.h:177
#define XBOX_ONE_MAX_ENDPOINTS
Definition: XBOXONE.h:37
#define NotifyFailUnknownDevice(...)
Definition: message.h:61
void setRumbleOff()
Definition: XBOXONE.cpp:450
@@ -113,14 +113,14 @@ $(function() {
uint16_t getButtonPress(ButtonEnum b)
Definition: XBOXONE.cpp:380
-
uint32_t qNextPollTime
Definition: XBOXONE.h:190
+
uint32_t qNextPollTime
Definition: XBOXONE.h:192
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
uint8_t bEndpointAddress
Definition: usb_ch9.h:151
uint8_t bmSndToggle
Definition: address.h:47
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:98
#define PSTR(str)
#define XBOX_ONE_INPUT_PIPE
Definition: XBOXONE.h:35
-
EpInfo epInfo[XBOX_ONE_MAX_ENDPOINTS]
Definition: XBOXONE.h:183
+
EpInfo epInfo[XBOX_ONE_MAX_ENDPOINTS]
Definition: XBOXONE.h:185
bool getButtonClick(ButtonEnum b)
Definition: XBOXONE.cpp:388
virtual uint8_t Poll()
Definition: XBOXONE.cpp:300
@@ -143,7 +143,7 @@ $(function() {
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:230
#define NotifyFailSetConfDescr(...)
Definition: message.h:60
-
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid)
Definition: XBOXONE.h:124
+
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid)
Definition: XBOXONE.h:125
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:796
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:58
void setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor)
Definition: XBOXONE.cpp:472
diff --git a/_x_b_o_x_o_n_e_8h.html b/_x_b_o_x_o_n_e_8h.html index 2322184b..9a8b1d65 100644 --- a/_x_b_o_x_o_n_e_8h.html +++ b/_x_b_o_x_o_n_e_8h.html @@ -118,6 +118,8 @@ Macros   #define XBOX_ONE_PID13   0x0B0A   +#define XBOX_ONE_PID14   0x0B12 +  #define XBOX_VID2   0x0738   #define XBOX_VID3   0x0E6F @@ -320,6 +322,22 @@ Macros

Definition at line 47 of file XBOXONE.h.

+
+
+ +

◆ XBOX_ONE_PID14

+ +
+
+ + + + +
#define XBOX_ONE_PID14   0x0B12
+
+ +

Definition at line 48 of file XBOXONE.h.

+
@@ -334,7 +352,7 @@ Macros
-

Definition at line 50 of file XBOXONE.h.

+

Definition at line 51 of file XBOXONE.h.

@@ -350,7 +368,7 @@ Macros
-

Definition at line 51 of file XBOXONE.h.

+

Definition at line 52 of file XBOXONE.h.

@@ -366,7 +384,7 @@ Macros
-

Definition at line 52 of file XBOXONE.h.

+

Definition at line 53 of file XBOXONE.h.

@@ -382,7 +400,7 @@ Macros
-

Definition at line 53 of file XBOXONE.h.

+

Definition at line 54 of file XBOXONE.h.

@@ -398,7 +416,7 @@ Macros
-

Definition at line 54 of file XBOXONE.h.

+

Definition at line 55 of file XBOXONE.h.

@@ -414,7 +432,7 @@ Macros
-

Definition at line 56 of file XBOXONE.h.

+

Definition at line 57 of file XBOXONE.h.

@@ -430,7 +448,7 @@ Macros
-

Definition at line 57 of file XBOXONE.h.

+

Definition at line 58 of file XBOXONE.h.

@@ -446,7 +464,7 @@ Macros
-

Definition at line 58 of file XBOXONE.h.

+

Definition at line 59 of file XBOXONE.h.

@@ -462,7 +480,7 @@ Macros
-

Definition at line 59 of file XBOXONE.h.

+

Definition at line 60 of file XBOXONE.h.

@@ -478,7 +496,7 @@ Macros
-

Definition at line 60 of file XBOXONE.h.

+

Definition at line 61 of file XBOXONE.h.

@@ -494,7 +512,7 @@ Macros
-

Definition at line 61 of file XBOXONE.h.

+

Definition at line 62 of file XBOXONE.h.

@@ -510,7 +528,7 @@ Macros
-

Definition at line 62 of file XBOXONE.h.

+

Definition at line 63 of file XBOXONE.h.

@@ -526,7 +544,7 @@ Macros
-

Definition at line 63 of file XBOXONE.h.

+

Definition at line 64 of file XBOXONE.h.

diff --git a/_x_b_o_x_o_n_e_8h_source.html b/_x_b_o_x_o_n_e_8h_source.html index 19824e9c..8f6660af 100644 --- a/_x_b_o_x_o_n_e_8h_source.html +++ b/_x_b_o_x_o_n_e_8h_source.html @@ -63,59 +63,60 @@ $(function() {
XBOXONE.h
-Go to the documentation of this file.
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2  Copyright (C) 2015 guruthree
3 
4  This software may be distributed and modified under the terms of the GNU
5  General Public License version 2 (GPL2) as published by the Free Software
6  Foundation and appearing in the file GPL2.TXT included in the packaging of
7  this file. Please note that GPL2 Section 2[b] requires that all works based
8  on this software must also be made publicly available under the terms of
9  the GPL2 ("Copyleft").
10 
11  Contact information
12  -------------------
13 
14  Kristian Lauszus, TKJ Electronics
15  Web : http://www.tkjelectronics.com
16  e-mail : kristianl@tkjelectronics.com
17 
18  guruthree
19  Web : https://github.com/guruthree/
20  */
21 
22 
23 #ifndef _xboxone_h_
24 #define _xboxone_h_
25 
26 #include "Usb.h"
27 #include "xboxEnums.h"
28 
29 /* Xbox One data taken from descriptors */
30 #define XBOX_ONE_EP_MAXPKTSIZE 64 // Max size for data via USB
31 
32 /* Names we give to the 3 XboxONE pipes */
33 #define XBOX_ONE_CONTROL_PIPE 0
34 #define XBOX_ONE_OUTPUT_PIPE 1
35 #define XBOX_ONE_INPUT_PIPE 2
36 
37 #define XBOX_ONE_MAX_ENDPOINTS 3
38 
39 // PID and VID of the different versions of the controller - see: https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c
40 
41 // Official controllers
42 #define XBOX_VID1 0x045E // Microsoft Corporation
43 #define XBOX_ONE_PID1 0x02D1 // Microsoft X-Box One pad
44 #define XBOX_ONE_PID2 0x02DD // Microsoft X-Box One pad (Firmware 2015)
45 #define XBOX_ONE_PID3 0x02E3 // Microsoft X-Box One Elite pad
46 #define XBOX_ONE_PID4 0x02EA // Microsoft X-Box One S pad
47 #define XBOX_ONE_PID13 0x0B0A // Microsoft X-Box One Adaptive Controller
48 
49 // Unofficial controllers
50 #define XBOX_VID2 0x0738 // Mad Catz
51 #define XBOX_VID3 0x0E6F // Afterglow
52 #define XBOX_VID4 0x0F0D // HORIPAD ONE
53 #define XBOX_VID5 0x1532 // Razer
54 #define XBOX_VID6 0x24C6 // PowerA
55 
56 #define XBOX_ONE_PID5 0x4A01 // Mad Catz FightStick TE 2 - might have different mapping for triggers?
57 #define XBOX_ONE_PID6 0x0139 // Afterglow Prismatic Wired Controller
58 #define XBOX_ONE_PID7 0x0146 // Rock Candy Wired Controller for Xbox One
59 #define XBOX_ONE_PID8 0x0067 // HORIPAD ONE
60 #define XBOX_ONE_PID9 0x0A03 // Razer Wildcat
61 #define XBOX_ONE_PID10 0x541A // PowerA Xbox One Mini Wired Controller
62 #define XBOX_ONE_PID11 0x542A // Xbox ONE spectra
63 #define XBOX_ONE_PID12 0x543A // PowerA Xbox One wired controller
64 
66 class XBOXONE : public USBDeviceConfig, public UsbConfigXtracter {
67 public:
72  XBOXONE(USB *pUsb);
73 
82  virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
87  virtual uint8_t Release();
92  virtual uint8_t Poll();
93 
98  virtual uint8_t GetAddress() {
99  return bAddress;
100  };
101 
106  virtual bool isReady() {
107  return bPollEnable;
108  };
109 
114  uint8_t readPollInterval() {
115  return pollInterval;
116  };
117 
124  virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
125  return ((vid == XBOX_VID1 || vid == XBOX_VID2 || vid == XBOX_VID3 || vid == XBOX_VID4 || vid == XBOX_VID5 || vid == XBOX_VID6) &&
126  (pid == XBOX_ONE_PID1 || pid == XBOX_ONE_PID2 || pid == XBOX_ONE_PID3 || pid == XBOX_ONE_PID4 ||
127  pid == XBOX_ONE_PID5 || pid == XBOX_ONE_PID6 || pid == XBOX_ONE_PID7 || pid == XBOX_ONE_PID8 ||
128  pid == XBOX_ONE_PID9 || pid == XBOX_ONE_PID10 || pid == XBOX_ONE_PID11 || pid == XBOX_ONE_PID12 || pid == XBOX_ONE_PID13));
129  };
143  uint16_t getButtonPress(ButtonEnum b);
144  bool getButtonClick(ButtonEnum b);
145 
151  int16_t getAnalogHat(AnalogHatEnum a);
152 
157  void attachOnInit(void (*funcOnInit)(void)) {
158  pFuncOnInit = funcOnInit;
159  };
160 
162  void setRumbleOff();
163 
171  void setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor);
176 
177 protected:
181  uint8_t bAddress;
184 
186  uint8_t bConfNum;
188  uint8_t bNumEP;
190  uint32_t qNextPollTime;
191 
201  void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
209 
210 private:
215  void onInit();
216  void (*pFuncOnInit)(void); // Pointer to function called in onInit()
217 
218  uint8_t pollInterval;
219  bool bPollEnable;
220 
221  /* Variables to store the buttons */
222  uint16_t ButtonState;
223  uint16_t OldButtonState;
224  uint16_t ButtonClickState;
225  int16_t hatValue[4];
226  uint16_t triggerValue[2];
227  uint16_t triggerValueOld[2];
228 
229  bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not
230  bool R2Clicked;
231 
232  uint8_t readBuf[XBOX_ONE_EP_MAXPKTSIZE]; // General purpose buffer for input data
233  uint8_t cmdCounter;
234 
235  void readReport(); // Used to read the incoming data
236 
237  /* Private commands */
238  uint8_t XboxCommand(uint8_t* data, uint16_t nbytes);
239 };
240 #endif
uint8_t bConfNum
Definition: XBOXONE.h:186
-
#define XBOX_ONE_PID5
Definition: XBOXONE.h:56
-
#define XBOX_ONE_PID10
Definition: XBOXONE.h:61
-
#define XBOX_ONE_PID9
Definition: XBOXONE.h:60
+Go to the documentation of this file.
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2  Copyright (C) 2015 guruthree
3 
4  This software may be distributed and modified under the terms of the GNU
5  General Public License version 2 (GPL2) as published by the Free Software
6  Foundation and appearing in the file GPL2.TXT included in the packaging of
7  this file. Please note that GPL2 Section 2[b] requires that all works based
8  on this software must also be made publicly available under the terms of
9  the GPL2 ("Copyleft").
10 
11  Contact information
12  -------------------
13 
14  Kristian Lauszus, TKJ Electronics
15  Web : http://www.tkjelectronics.com
16  e-mail : kristianl@tkjelectronics.com
17 
18  guruthree
19  Web : https://github.com/guruthree/
20  */
21 
22 
23 #ifndef _xboxone_h_
24 #define _xboxone_h_
25 
26 #include "Usb.h"
27 #include "xboxEnums.h"
28 
29 /* Xbox One data taken from descriptors */
30 #define XBOX_ONE_EP_MAXPKTSIZE 64 // Max size for data via USB
31 
32 /* Names we give to the 3 XboxONE pipes */
33 #define XBOX_ONE_CONTROL_PIPE 0
34 #define XBOX_ONE_OUTPUT_PIPE 1
35 #define XBOX_ONE_INPUT_PIPE 2
36 
37 #define XBOX_ONE_MAX_ENDPOINTS 3
38 
39 // PID and VID of the different versions of the controller - see: https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c
40 
41 // Official controllers
42 #define XBOX_VID1 0x045E // Microsoft Corporation
43 #define XBOX_ONE_PID1 0x02D1 // Microsoft X-Box One pad
44 #define XBOX_ONE_PID2 0x02DD // Microsoft X-Box One pad (Firmware 2015)
45 #define XBOX_ONE_PID3 0x02E3 // Microsoft X-Box One Elite pad
46 #define XBOX_ONE_PID4 0x02EA // Microsoft X-Box One S pad
47 #define XBOX_ONE_PID13 0x0B0A // Microsoft X-Box One Adaptive Controller
48 #define XBOX_ONE_PID14 0x0B12 // Microsoft X-Box Core Controller
49 
50 // Unofficial controllers
51 #define XBOX_VID2 0x0738 // Mad Catz
52 #define XBOX_VID3 0x0E6F // Afterglow
53 #define XBOX_VID4 0x0F0D // HORIPAD ONE
54 #define XBOX_VID5 0x1532 // Razer
55 #define XBOX_VID6 0x24C6 // PowerA
56 
57 #define XBOX_ONE_PID5 0x4A01 // Mad Catz FightStick TE 2 - might have different mapping for triggers?
58 #define XBOX_ONE_PID6 0x0139 // Afterglow Prismatic Wired Controller
59 #define XBOX_ONE_PID7 0x0146 // Rock Candy Wired Controller for Xbox One
60 #define XBOX_ONE_PID8 0x0067 // HORIPAD ONE
61 #define XBOX_ONE_PID9 0x0A03 // Razer Wildcat
62 #define XBOX_ONE_PID10 0x541A // PowerA Xbox One Mini Wired Controller
63 #define XBOX_ONE_PID11 0x542A // Xbox ONE spectra
64 #define XBOX_ONE_PID12 0x543A // PowerA Xbox One wired controller
65 
67 class XBOXONE : public USBDeviceConfig, public UsbConfigXtracter {
68 public:
73  XBOXONE(USB *pUsb);
74 
83  virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
88  virtual uint8_t Release();
93  virtual uint8_t Poll();
94 
99  virtual uint8_t GetAddress() {
100  return bAddress;
101  };
102 
107  virtual bool isReady() {
108  return bPollEnable;
109  };
110 
115  uint8_t readPollInterval() {
116  return pollInterval;
117  };
118 
125  virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
126  return ((vid == XBOX_VID1 || vid == XBOX_VID2 || vid == XBOX_VID3 || vid == XBOX_VID4 || vid == XBOX_VID5 || vid == XBOX_VID6) &&
127  (pid == XBOX_ONE_PID1 || pid == XBOX_ONE_PID2 || pid == XBOX_ONE_PID3 || pid == XBOX_ONE_PID4 ||
128  pid == XBOX_ONE_PID5 || pid == XBOX_ONE_PID6 || pid == XBOX_ONE_PID7 || pid == XBOX_ONE_PID8 ||
129  pid == XBOX_ONE_PID9 || pid == XBOX_ONE_PID10 || pid == XBOX_ONE_PID11 || pid == XBOX_ONE_PID12 ||
130  pid == XBOX_ONE_PID13 || pid == XBOX_ONE_PID14));
131  };
145  uint16_t getButtonPress(ButtonEnum b);
146  bool getButtonClick(ButtonEnum b);
147 
153  int16_t getAnalogHat(AnalogHatEnum a);
154 
159  void attachOnInit(void (*funcOnInit)(void)) {
160  pFuncOnInit = funcOnInit;
161  };
162 
164  void setRumbleOff();
165 
173  void setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor);
178 
179 protected:
183  uint8_t bAddress;
186 
188  uint8_t bConfNum;
190  uint8_t bNumEP;
192  uint32_t qNextPollTime;
193 
203  void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
211 
212 private:
217  void onInit();
218  void (*pFuncOnInit)(void); // Pointer to function called in onInit()
219 
220  uint8_t pollInterval;
221  bool bPollEnable;
222 
223  /* Variables to store the buttons */
224  uint16_t ButtonState;
225  uint16_t OldButtonState;
226  uint16_t ButtonClickState;
227  int16_t hatValue[4];
228  uint16_t triggerValue[2];
229  uint16_t triggerValueOld[2];
230 
231  bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not
232  bool R2Clicked;
233 
234  uint8_t readBuf[XBOX_ONE_EP_MAXPKTSIZE]; // General purpose buffer for input data
235  uint8_t cmdCounter;
236 
237  void readReport(); // Used to read the incoming data
238 
239  /* Private commands */
240  uint8_t XboxCommand(uint8_t* data, uint16_t nbytes);
241 };
242 #endif
uint8_t bConfNum
Definition: XBOXONE.h:188
+
#define XBOX_ONE_PID5
Definition: XBOXONE.h:57
+
#define XBOX_ONE_PID10
Definition: XBOXONE.h:62
+
#define XBOX_ONE_PID9
Definition: XBOXONE.h:61
-
virtual bool isReady()
Definition: XBOXONE.h:106
+
virtual bool isReady()
Definition: XBOXONE.h:107
#define XBOX_ONE_EP_MAXPKTSIZE
Definition: XBOXONE.h:30
-
USB * pUsb
Definition: XBOXONE.h:179
-
void attachOnInit(void(*funcOnInit)(void))
Definition: XBOXONE.h:157
+
USB * pUsb
Definition: XBOXONE.h:181
+
void attachOnInit(void(*funcOnInit)(void))
Definition: XBOXONE.h:159
AnalogHatEnum
-
uint8_t bAddress
Definition: XBOXONE.h:181
+
uint8_t bAddress
Definition: XBOXONE.h:183
XBOXONE(USB *pUsb)
Definition: XBOXONE.cpp:27
-
#define XBOX_VID3
Definition: XBOXONE.h:51
+
#define XBOX_ONE_PID14
Definition: XBOXONE.h:48
+
#define XBOX_VID3
Definition: XBOXONE.h:52
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: XBOXONE.cpp:239
-
uint8_t bNumEP
Definition: XBOXONE.h:188
-
#define XBOX_VID6
Definition: XBOXONE.h:54
+
uint8_t bNumEP
Definition: XBOXONE.h:190
+
#define XBOX_VID6
Definition: XBOXONE.h:55
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)
Definition: XBOXONE.cpp:265
-
bool XboxOneConnected
Definition: XBOXONE.h:175
+
bool XboxOneConnected
Definition: XBOXONE.h:177
#define XBOX_ONE_MAX_ENDPOINTS
Definition: XBOXONE.h:37
-
#define XBOX_VID2
Definition: XBOXONE.h:50
+
#define XBOX_VID2
Definition: XBOXONE.h:51
void setRumbleOff()
Definition: XBOXONE.cpp:450
-
#define XBOX_ONE_PID8
Definition: XBOXONE.h:59
+
#define XBOX_ONE_PID8
Definition: XBOXONE.h:60
virtual uint8_t Release()
Definition: XBOXONE.cpp:286
-
#define XBOX_VID4
Definition: XBOXONE.h:52
+
#define XBOX_VID4
Definition: XBOXONE.h:53
Definition: address.h:39
ButtonEnum
uint16_t getButtonPress(ButtonEnum b)
Definition: XBOXONE.cpp:380
-
virtual uint8_t GetAddress()
Definition: XBOXONE.h:98
-
uint32_t qNextPollTime
Definition: XBOXONE.h:190
+
virtual uint8_t GetAddress()
Definition: XBOXONE.h:99
+
uint32_t qNextPollTime
Definition: XBOXONE.h:192
#define XBOX_ONE_PID2
Definition: XBOXONE.h:44
-
EpInfo epInfo[XBOX_ONE_MAX_ENDPOINTS]
Definition: XBOXONE.h:183
+
EpInfo epInfo[XBOX_ONE_MAX_ENDPOINTS]
Definition: XBOXONE.h:185
bool getButtonClick(ButtonEnum b)
Definition: XBOXONE.cpp:388
-
uint8_t readPollInterval()
Definition: XBOXONE.h:114
+
uint8_t readPollInterval()
Definition: XBOXONE.h:115
virtual uint8_t Poll()
Definition: XBOXONE.cpp:300
-
#define XBOX_ONE_PID11
Definition: XBOXONE.h:62
+
#define XBOX_ONE_PID11
Definition: XBOXONE.h:63
#define XBOX_ONE_PID4
Definition: XBOXONE.h:46
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: XBOXONE.cpp:46
-
#define XBOX_ONE_PID7
Definition: XBOXONE.h:58
+
#define XBOX_ONE_PID7
Definition: XBOXONE.h:59
#define XBOX_ONE_PID13
Definition: XBOXONE.h:47
-
#define XBOX_ONE_PID12
Definition: XBOXONE.h:63
+
#define XBOX_ONE_PID12
Definition: XBOXONE.h:64
Definition: UsbCore.h:210
-
#define XBOX_VID5
Definition: XBOXONE.h:53
-
#define XBOX_ONE_PID6
Definition: XBOXONE.h:57
+
#define XBOX_VID5
Definition: XBOXONE.h:54
+
#define XBOX_ONE_PID6
Definition: XBOXONE.h:58
int16_t getAnalogHat(AnalogHatEnum a)
Definition: XBOXONE.cpp:408
#define XBOX_VID1
Definition: XBOXONE.h:42
- +
#define XBOX_ONE_PID1
Definition: XBOXONE.h:43
#define XBOX_ONE_PID3
Definition: XBOXONE.h:45
-
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid)
Definition: XBOXONE.h:124
+
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid)
Definition: XBOXONE.h:125
void setRumbleOn(uint8_t leftTrigger, uint8_t rightTrigger, uint8_t leftMotor, uint8_t rightMotor)
Definition: XBOXONE.cpp:472
diff --git a/class_u_s_b_device_config.html b/class_u_s_b_device_config.html index 05d5eb30..bd50552c 100644 --- a/class_u_s_b_device_config.html +++ b/class_u_s_b_device_config.html @@ -236,7 +236,7 @@ Public Member Functions
-

Reimplemented in BulkOnly, BTD, HIDBoot< BOOT_PROTOCOL >, ACM, USBHub, FTDI, ADK, HIDUniversal, USBH_MIDI, HIDComposite, XBOXONE, XBOXRECV, XBOXUSB, PS3USB, and XBOXOLD.

+

Reimplemented in BulkOnly, BTD, HIDBoot< BOOT_PROTOCOL >, ACM, USBHub, FTDI, ADK, HIDUniversal, USBH_MIDI, XBOXONE, HIDComposite, XBOXRECV, XBOXUSB, PS3USB, and XBOXOLD.

Definition at line 145 of file UsbCore.h.

diff --git a/class_x_b_o_x_o_n_e.html b/class_x_b_o_x_o_n_e.html index adaf3ba8..bc54d6cb 100644 --- a/class_x_b_o_x_o_n_e.html +++ b/class_x_b_o_x_o_n_e.html @@ -166,7 +166,7 @@ Protected Attributes

Detailed Description

This class implements support for a Xbox ONE controller connected via USB.

-

Definition at line 66 of file XBOXONE.h.

+

Definition at line 67 of file XBOXONE.h.

Constructor & Destructor Documentation

◆ XBOXONE()

@@ -336,7 +336,7 @@ Protected Attributes

Reimplemented from USBDeviceConfig.

-

Definition at line 98 of file XBOXONE.h.

+

Definition at line 99 of file XBOXONE.h.

@@ -364,7 +364,7 @@ Protected Attributes

Used to check if the controller has been initialized.

Returns
True if it's ready.
-

Definition at line 106 of file XBOXONE.h.

+

Definition at line 107 of file XBOXONE.h.

@@ -392,7 +392,7 @@ Protected Attributes

Read the poll interval taken from the endpoint descriptors.

Returns
The poll interval in ms.
-

Definition at line 114 of file XBOXONE.h.

+

Definition at line 115 of file XBOXONE.h.

@@ -440,7 +440,7 @@ Protected Attributes

Reimplemented from USBDeviceConfig.

-

Definition at line 124 of file XBOXONE.h.

+

Definition at line 125 of file XBOXONE.h.

@@ -559,7 +559,7 @@ Protected Attributes -

Definition at line 157 of file XBOXONE.h.

+

Definition at line 159 of file XBOXONE.h.

@@ -750,7 +750,7 @@ Protected Attributes

True if a Xbox ONE controller is connected.

-

Definition at line 175 of file XBOXONE.h.

+

Definition at line 177 of file XBOXONE.h.

@@ -775,7 +775,7 @@ Protected Attributes

Pointer to USB class instance.

-

Definition at line 179 of file XBOXONE.h.

+

Definition at line 181 of file XBOXONE.h.

@@ -800,7 +800,7 @@ Protected Attributes

Device address.

-

Definition at line 181 of file XBOXONE.h.

+

Definition at line 183 of file XBOXONE.h.

@@ -825,7 +825,7 @@ Protected Attributes

Endpoint info structure.

-

Definition at line 183 of file XBOXONE.h.

+

Definition at line 185 of file XBOXONE.h.

@@ -850,7 +850,7 @@ Protected Attributes

Configuration number.

-

Definition at line 186 of file XBOXONE.h.

+

Definition at line 188 of file XBOXONE.h.

@@ -875,7 +875,7 @@ Protected Attributes

Total number of endpoints in the configuration.

-

Definition at line 188 of file XBOXONE.h.

+

Definition at line 190 of file XBOXONE.h.

@@ -900,7 +900,7 @@ Protected Attributes

Next poll time based on poll interval taken from the USB descriptor.

-

Definition at line 190 of file XBOXONE.h.

+

Definition at line 192 of file XBOXONE.h.

diff --git a/globals_defs_x.html b/globals_defs_x.html index e6966810..20981b2f 100644 --- a/globals_defs_x.html +++ b/globals_defs_x.html @@ -130,6 +130,9 @@ $(function() {
  • XBOX_ONE_PID13 : XBOXONE.h
  • +
  • XBOX_ONE_PID14 +: XBOXONE.h +
  • XBOX_ONE_PID2 : XBOXONE.h
  • diff --git a/globals_eval.html b/globals_eval.html index 408d95c9..8744d152 100644 --- a/globals_eval.html +++ b/globals_eval.html @@ -551,12 +551,12 @@ $(function() {

    - w -

    diff --git a/globals_w.html b/globals_w.html index d7619b4e..b4b5a6f8 100644 --- a/globals_w.html +++ b/globals_w.html @@ -62,12 +62,12 @@ $(function() {
    Here is a list of all file members with links to the files they belong to:

    - w -