diff --git a/_p_s4_parser_8cpp_source.html b/_p_s4_parser_8cpp_source.html index e0a07fc0..d4b23eea 100644 --- a/_p_s4_parser_8cpp_source.html +++ b/_p_s4_parser_8cpp_source.html @@ -63,7 +63,7 @@ $(function() {
PS4Parser.cpp
-Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #include "PS4Parser.h"
19 
20 enum DPADEnum {
21  DPAD_UP = 0x0,
23  DPAD_RIGHT = 0x2,
25  DPAD_DOWN = 0x4,
27  DPAD_LEFT = 0x6,
28  DPAD_LEFT_UP = 0x7,
29  DPAD_OFF = 0x8,
30 };
31 
32 // To enable serial debugging see "settings.h"
33 //#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller
34 
35 bool PS4Parser::checkDpad(ButtonEnum b) {
36  switch (b) {
37  case UP:
38  return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT;
39  case RIGHT:
40  return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN;
41  case DOWN:
42  return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT;
43  case LEFT:
44  return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP;
45  default:
46  return false;
47  }
48 }
49 
51  if (b <= LEFT) // Dpad
52  return checkDpad(b);
53  else
54  return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]));
55 }
56 
58  uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]);
59  bool click = buttonClickState.val & mask;
60  buttonClickState.val &= ~mask; // Clear "click" event
61  return click;
62 }
63 
65  if (b == L2) // These are the only analog buttons on the controller
66  return ps4Data.trigger[0];
67  else if (b == R2)
68  return ps4Data.trigger[1];
69  return 0;
70 }
71 
73  return ps4Data.hatValue[(uint8_t)a];
74 }
75 
76 void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
77  if (len > 1 && buf) {
78 #ifdef PRINTREPORT
79  Notify(PSTR("\r\n"), 0x80);
80  for (uint8_t i = 0; i < len; i++) {
81  D_PrintHex<uint8_t > (buf[i], 0x80);
82  Notify(PSTR(" "), 0x80);
83  }
84 #endif
85 
86  if (buf[0] == 0x01) // Check report ID
87  memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(ps4Data)));
88  else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
89  if (len < 4) {
90 #ifdef DEBUG_USB_HOST
91  Notify(PSTR("\r\nReport is too short: "), 0x80);
92  D_PrintHex<uint8_t > (len, 0x80);
93 #endif
94  return;
95  }
96  memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), MFK_CASTUINT8T sizeof(ps4Data)));
97  } else {
98 #ifdef DEBUG_USB_HOST
99  Notify(PSTR("\r\nUnknown report id: "), 0x80);
100  D_PrintHex<uint8_t > (buf[0], 0x80);
101 #endif
102  return;
103  }
104 
105  if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed
106  buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable
107  oldButtonState.val = ps4Data.btn.val;
108 
109  // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself
110  uint8_t newDpad = 0;
111  if (checkDpad(UP))
112  newDpad |= 1 << UP;
113  if (checkDpad(RIGHT))
114  newDpad |= 1 << RIGHT;
115  if (checkDpad(DOWN))
116  newDpad |= 1 << DOWN;
117  if (checkDpad(LEFT))
118  newDpad |= 1 << LEFT;
119  if (newDpad != oldDpad) {
120  buttonClickState.dpad = newDpad & ~oldDpad; // Override values
121  oldDpad = newDpad;
122  }
123  }
124  }
125 
126  if (ps4Output.reportChanged)
127  sendOutputReport(&ps4Output); // Send output report
128 }
129 
131  uint8_t i;
132  for (i = 0; i < sizeof(ps4Data.hatValue); i++)
133  ps4Data.hatValue[i] = 127; // Center value
134  ps4Data.btn.val = 0;
135  oldButtonState.val = 0;
136  for (i = 0; i < sizeof(ps4Data.trigger); i++)
137  ps4Data.trigger[i] = 0;
138  for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {
139  for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)
140  ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad
141  }
142 
143  ps4Data.btn.dpad = DPAD_OFF;
144  oldButtonState.dpad = DPAD_OFF;
145  buttonClickState.dpad = 0;
146  oldDpad = 0;
147 
148  ps4Output.bigRumble = ps4Output.smallRumble = 0;
149  ps4Output.r = ps4Output.g = ps4Output.b = 0;
150  ps4Output.flashOn = ps4Output.flashOff = 0;
151  ps4Output.reportChanged = false;
152 };
153 
+Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #include "PS4Parser.h"
19 
20 enum DPADEnum {
21  DPAD_UP = 0x0,
23  DPAD_RIGHT = 0x2,
25  DPAD_DOWN = 0x4,
27  DPAD_LEFT = 0x6,
28  DPAD_LEFT_UP = 0x7,
29  DPAD_OFF = 0x8,
30 };
31 
32 // To enable serial debugging see "settings.h"
33 //#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller
34 
35 bool PS4Parser::checkDpad(ButtonEnum b) {
36  switch (b) {
37  case UP:
38  return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT;
39  case RIGHT:
40  return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN;
41  case DOWN:
42  return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT;
43  case LEFT:
44  return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP;
45  default:
46  return false;
47  }
48 }
49 
51  if (b <= LEFT) // Dpad
52  return checkDpad(b);
53  else
54  return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]));
55 }
56 
58  uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]);
59  bool click = buttonClickState.val & mask;
60  buttonClickState.val &= ~mask; // Clear "click" event
61  return click;
62 }
63 
65  if (b == L2) // These are the only analog buttons on the controller
66  return ps4Data.trigger[0];
67  else if (b == R2)
68  return ps4Data.trigger[1];
69  return 0;
70 }
71 
73  return ps4Data.hatValue[(uint8_t)a];
74 }
75 
76 void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
77  if (len > 1 && buf) {
78 #ifdef PRINTREPORT
79  Notify(PSTR("\r\n"), 0x80);
80  for (uint8_t i = 0; i < len; i++) {
81  D_PrintHex<uint8_t > (buf[i], 0x80);
82  Notify(PSTR(" "), 0x80);
83  }
84 #endif
85 
86  if (buf[0] == 0x01) // Check report ID
87  memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(ps4Data)));
88  else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
89  if (len < 4) {
90 #ifdef DEBUG_USB_HOST
91  Notify(PSTR("\r\nReport is too short: "), 0x80);
92  D_PrintHex<uint8_t > (len, 0x80);
93 #endif
94  return;
95  }
96  memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), MFK_CASTUINT8T sizeof(ps4Data)));
97  } else {
98 #ifdef DEBUG_USB_HOST
99  Notify(PSTR("\r\nUnknown report id: "), 0x80);
100  D_PrintHex<uint8_t > (buf[0], 0x80);
101 #endif
102  return;
103  }
104 
105  if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed
106  buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable
107  oldButtonState.val = ps4Data.btn.val;
108 
109  // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself
110  uint8_t newDpad = 0;
111  if (checkDpad(UP))
112  newDpad |= 1 << UP;
113  if (checkDpad(RIGHT))
114  newDpad |= 1 << RIGHT;
115  if (checkDpad(DOWN))
116  newDpad |= 1 << DOWN;
117  if (checkDpad(LEFT))
118  newDpad |= 1 << LEFT;
119  if (newDpad != oldDpad) {
120  buttonClickState.dpad = newDpad & ~oldDpad; // Override values
121  oldDpad = newDpad;
122  }
123  }
124  }
125 
126  if (ps4Output.reportChanged)
127  sendOutputReport(&ps4Output); // Send output report
128 }
129 
131  uint8_t i;
132  for (i = 0; i < sizeof(ps4Data.hatValue); i++)
133  ps4Data.hatValue[i] = 127; // Center value
134  ps4Data.btn.val = 0;
135  oldButtonState.val = 0;
136  for (i = 0; i < sizeof(ps4Data.trigger); i++)
137  ps4Data.trigger[i] = 0;
138  for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {
139  for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)
140  ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad
141  }
142 
143  ps4Data.btn.dpad = DPAD_OFF;
144  oldButtonState.dpad = DPAD_OFF;
145  buttonClickState.dpad = 0;
146  oldDpad = 0;
147 
148  ps4Output.bigRumble = ps4Output.smallRumble = 0;
149  ps4Output.r = ps4Output.g = ps4Output.b = 0;
150  ps4Output.flashOn = ps4Output.flashOff = 0;
151  ps4Output.reportChanged = false;
152 };
153 
void Reset()
Definition: PS4Parser.cpp:130
uint32_t val
Definition: PS4Parser.h:71
@@ -75,6 +75,7 @@ $(function() {
uint8_t touching
Definition: PS4Parser.h:78
uint8_t flashOn
Definition: PS4Parser.h:119
+
struct touchpadXY::@28 finger[2]
#define pgm_read_byte(addr)
@@ -97,7 +98,6 @@ $(function() {
#define PSTR(str)
#define MFK_CASTUINT8T
Definition: settings.h:194
uint8_t dpad
Definition: PS4Parser.h:52
-
struct touchpadXY::@30 finger[2]
touchpadXY xy[3]
Definition: PS4Parser.h:108
uint8_t getAnalogButton(ButtonEnum b)
Definition: PS4Parser.cpp:64
PS4Buttons btn
Definition: PS4Parser.h:95
diff --git a/_p_s4_u_s_b_8h.html b/_p_s4_u_s_b_8h.html index f43d8d34..f5182e32 100644 --- a/_p_s4_u_s_b_8h.html +++ b/_p_s4_u_s_b_8h.html @@ -73,12 +73,13 @@ Include dependency graph for PS4USB.h:
- - - - - - + + + + + + +
diff --git a/_p_s4_u_s_b_8h__incl.map b/_p_s4_u_s_b_8h__incl.map index c0f16df6..6d487681 100644 --- a/_p_s4_u_s_b_8h__incl.map +++ b/_p_s4_u_s_b_8h__incl.map @@ -1,8 +1,9 @@ - - - - - - + + + + + + + diff --git a/_p_s4_u_s_b_8h__incl.md5 b/_p_s4_u_s_b_8h__incl.md5 index 76233869..0dee2be9 100644 --- a/_p_s4_u_s_b_8h__incl.md5 +++ b/_p_s4_u_s_b_8h__incl.md5 @@ -1 +1 @@ -d2a18154f1cb36761bff05421187bd1f \ No newline at end of file +666bd76bcef94225b45bfa8ed7ffd0a5 \ No newline at end of file diff --git a/_p_s4_u_s_b_8h__incl.png b/_p_s4_u_s_b_8h__incl.png index 6686645c..c0827f61 100644 Binary files a/_p_s4_u_s_b_8h__incl.png and b/_p_s4_u_s_b_8h__incl.png differ diff --git a/_p_s4_u_s_b_8h_source.html b/_p_s4_u_s_b_8h_source.html index 143a802a..0a4e615a 100644 --- a/_p_s4_u_s_b_8h_source.html +++ b/_p_s4_u_s_b_8h_source.html @@ -63,20 +63,19 @@ $(function() {
PS4USB.h
-Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #ifndef _ps4usb_h_
19 #define _ps4usb_h_
20 
21 #include "hiduniversal.h"
22 #include "PS4Parser.h"
23 
24 #define PS4_VID 0x054C // Sony Corporation
25 #define PS4_PID 0x05C4 // PS4 Controller
26 #define PS4_PID_SLIM 0x09CC // PS4 Slim Controller
27 
32 class PS4USB : public HIDUniversal, public PS4Parser {
33 public:
38  PS4USB(USB *p) :
39  HIDUniversal(p) {
41  };
42 
47  bool connected() {
48  return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM);
49  };
50 
55  void attachOnInit(void (*funcOnInit)(void)) {
56  pFuncOnInit = funcOnInit;
57  };
58 
59 protected:
68  virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
70  PS4Parser::Parse(len, buf);
71  };
72 
78  virtual uint8_t OnInitSuccessful() {
81  if (pFuncOnInit)
82  pFuncOnInit(); // Call the user function
83  else
84  setLed(Blue);
85  };
86  return 0;
87  };
91  virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv
92  uint8_t buf[32];
93  memset(buf, 0, sizeof(buf));
94 
95  buf[0] = 0x05; // Report ID
96  buf[1]= 0xFF;
97 
98  buf[4] = output->smallRumble; // Small Rumble
99  buf[5] = output->bigRumble; // Big rumble
100 
101  buf[6] = output->r; // Red
102  buf[7] = output->g; // Green
103  buf[8] = output->b; // Blue
104 
105  buf[9] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)
106  buf[10] = output->flashOff; // Time to flash dark (255 = 2.5 seconds)
107 
108  output->reportChanged = false;
109 
110  // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed
111 
112  pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, sizeof(buf), buf);
113  };
123  virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
124  return (vid == PS4_VID && (pid == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM));
125  };
128 private:
129  void (*pFuncOnInit)(void); // Pointer to function called in onInit()
130 };
131 #endif
uint16_t PID
Definition: hiduniversal.h:69
-
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid)
Definition: PS4USB.h:123
+Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #ifndef _ps4usb_h_
19 #define _ps4usb_h_
20 
21 #include "hiduniversal.h"
22 #include "PS4Parser.h"
23 
24 #define PS4_VID 0x054C // Sony Corporation
25 #define PS4_PID 0x05C4 // PS4 Controller
26 #define PS4_PID_SLIM 0x09CC // PS4 Slim Controller
27 
32 class PS4USB : public HIDUniversal, public PS4Parser {
33 public:
38  PS4USB(USB *p) :
39  HIDUniversal(p) {
41  };
42 
47  bool connected() {
48  return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM);
49  };
50 
55  void attachOnInit(void (*funcOnInit)(void)) {
56  pFuncOnInit = funcOnInit;
57  };
58 
59 protected:
68  virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
70  PS4Parser::Parse(len, buf);
71  };
72 
78  virtual uint8_t OnInitSuccessful() {
81  if (pFuncOnInit)
82  pFuncOnInit(); // Call the user function
83  else
84  setLed(Blue);
85  };
86  return 0;
87  };
91  virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv
92  uint8_t buf[32];
93  memset(buf, 0, sizeof(buf));
94 
95  buf[0] = 0x05; // Report ID
96  buf[1]= 0xFF;
97 
98  buf[4] = output->smallRumble; // Small Rumble
99  buf[5] = output->bigRumble; // Big rumble
100 
101  buf[6] = output->r; // Red
102  buf[7] = output->g; // Green
103  buf[8] = output->b; // Blue
104 
105  buf[9] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)
106  buf[10] = output->flashOff; // Time to flash dark (255 = 2.5 seconds)
107 
108  output->reportChanged = false;
109 
110  // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed
111 
112  pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, sizeof(buf), buf);
113  };
123  virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
124  return (vid == PS4_VID && (pid == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM));
125  };
128 private:
129  void (*pFuncOnInit)(void); // Pointer to function called in onInit()
130 };
131 #endif
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid)
Definition: PS4USB.h:123
Definition: usbhid.h:143
void Reset()
Definition: PS4Parser.cpp:130
USB * pUsb
Definition: usbhid.h:145
void attachOnInit(void(*funcOnInit)(void))
Definition: PS4USB.h:55
-
virtual bool isReady()
Definition: hiduniversal.h:97
virtual uint8_t OnInitSuccessful()
Definition: PS4USB.h:78
uint8_t b
Definition: PS4Parser.h:118
void setLed(uint8_t r, uint8_t g, uint8_t b)
Definition: PS4Parser.h:320
+
virtual bool isReady()
Definition: hidcomposite.h:99
Definition: PS4USB.h:32
uint8_t flashOn
Definition: PS4Parser.h:119
-
uint16_t VID
Definition: hiduniversal.h:69
+
EpInfo epInfo[totalEndpoints]
Definition: hidcomposite.h:63
uint8_t g
Definition: PS4Parser.h:118
bool reportChanged
Definition: PS4Parser.h:120
void Parse(uint8_t len, uint8_t *buf)
Definition: PS4Parser.cpp:76
@@ -85,12 +84,14 @@ $(function() {
uint8_t bAddress
Definition: usbhid.h:146
uint8_t r
Definition: PS4Parser.h:118
uint8_t bigRumble
Definition: PS4Parser.h:117
+
uint16_t PID
Definition: hidcomposite.h:71
bool connected()
Definition: PS4USB.h:47
uint8_t flashOff
Definition: PS4Parser.h:119
uint8_t smallRumble
Definition: PS4Parser.h:117
+
uint16_t VID
Definition: hidcomposite.h:71
#define PS4_VID
Definition: PS4USB.h:24
#define PS4_PID_SLIM
Definition: PS4USB.h:26
@@ -98,9 +99,8 @@ $(function() {
virtual void sendOutputReport(PS4Output *output)
Definition: PS4USB.h:91
PS4USB(USB *p)
Definition: PS4USB.h:38
Definition: UsbCore.h:210
-
EpInfo epInfo[totalEndpoints]
Definition: hiduniversal.h:64
virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
Definition: PS4USB.h:68
- +
- - - - - - + + + + + + +
diff --git a/_p_s_buzz_8cpp__incl.map b/_p_s_buzz_8cpp__incl.map index 6dfe1b5c..6950499c 100644 --- a/_p_s_buzz_8cpp__incl.map +++ b/_p_s_buzz_8cpp__incl.map @@ -1,8 +1,9 @@ - - - - - - + + + + + + + diff --git a/_p_s_buzz_8cpp__incl.md5 b/_p_s_buzz_8cpp__incl.md5 index 254fa80c..fda19d77 100644 --- a/_p_s_buzz_8cpp__incl.md5 +++ b/_p_s_buzz_8cpp__incl.md5 @@ -1 +1 @@ -5a74379adade31d51d1b0ef98c2b52fe \ No newline at end of file +d36c8d74a36d7e8cc48ee208ff183cac \ No newline at end of file diff --git a/_p_s_buzz_8cpp__incl.png b/_p_s_buzz_8cpp__incl.png index ff801c84..a96ecccf 100644 Binary files a/_p_s_buzz_8cpp__incl.png and b/_p_s_buzz_8cpp__incl.png differ diff --git a/_p_s_buzz_8cpp_source.html b/_p_s_buzz_8cpp_source.html index 1b7935d9..e15a47b2 100644 --- a/_p_s_buzz_8cpp_source.html +++ b/_p_s_buzz_8cpp_source.html @@ -63,14 +63,13 @@ $(function() {
PSBuzz.cpp
-Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #include "PSBuzz.h"
19 
20 // To enable serial debugging see "settings.h"
21 //#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers
22 
23 void PSBuzz::ParseHIDData(USBHID *hid __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len, uint8_t *buf) {
24  if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 2 && buf) {
25 #ifdef PRINTREPORT
26  Notify(PSTR("\r\n"), 0x80);
27  for (uint8_t i = 0; i < len; i++) {
28  D_PrintHex<uint8_t > (buf[i], 0x80);
29  Notify(PSTR(" "), 0x80);
30  }
31 #endif
32  memcpy(&psbuzzButtons, buf + 2, min((uint8_t)(len - 2), MFK_CASTUINT8T sizeof(psbuzzButtons)));
33 
34  if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed
35  buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable
36  oldButtonState.val = psbuzzButtons.val;
37  }
38  }
39 };
40 
43  Reset();
44  if (pFuncOnInit)
45  pFuncOnInit(); // Call the user function
46  else
47  setLedOnAll(); // Turn the LED on, on all four controllers
48  };
49  return 0;
50 };
51 
52 bool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) {
53  return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
54 };
55 
56 bool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) {
57  uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
58  bool click = buttonClickState.val & mask;
59  buttonClickState.val &= ~mask; // Clear "click" event
60  return click;
61 };
62 
63 // Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c
64 void PSBuzz::setLedRaw(bool value, uint8_t controller) {
65  ledState[controller] = value; // Save value for next time it is called
66 
67  uint8_t buf[7];
68  buf[0] = 0x00;
69  buf[1] = ledState[0] ? 0xFF : 0x00;
70  buf[2] = ledState[1] ? 0xFF : 0x00;
71  buf[3] = ledState[2] ? 0xFF : 0x00;
72  buf[4] = ledState[3] ? 0xFF : 0x00;
73  buf[5] = 0x00;
74  buf[6] = 0x00;
75 
76  PSBuzz_Command(buf, sizeof(buf));
77 };
78 
79 void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) {
80  // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
81  pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
82 };
uint16_t PID
Definition: hiduniversal.h:69
-
Definition: usbhid.h:143
+Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #include "PSBuzz.h"
19 
20 // To enable serial debugging see "settings.h"
21 //#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers
22 
23 void PSBuzz::ParseHIDData(USBHID *hid __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len, uint8_t *buf) {
24  if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 2 && buf) {
25 #ifdef PRINTREPORT
26  Notify(PSTR("\r\n"), 0x80);
27  for (uint8_t i = 0; i < len; i++) {
28  D_PrintHex<uint8_t > (buf[i], 0x80);
29  Notify(PSTR(" "), 0x80);
30  }
31 #endif
32  memcpy(&psbuzzButtons, buf + 2, min((uint8_t)(len - 2), MFK_CASTUINT8T sizeof(psbuzzButtons)));
33 
34  if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed
35  buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable
36  oldButtonState.val = psbuzzButtons.val;
37  }
38  }
39 };
40 
43  Reset();
44  if (pFuncOnInit)
45  pFuncOnInit(); // Call the user function
46  else
47  setLedOnAll(); // Turn the LED on, on all four controllers
48  };
49  return 0;
50 };
51 
52 bool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) {
53  return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
54 };
55 
56 bool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) {
57  uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
58  bool click = buttonClickState.val & mask;
59  buttonClickState.val &= ~mask; // Clear "click" event
60  return click;
61 };
62 
63 // Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c
64 void PSBuzz::setLedRaw(bool value, uint8_t controller) {
65  ledState[controller] = value; // Save value for next time it is called
66 
67  uint8_t buf[7];
68  buf[0] = 0x00;
69  buf[1] = ledState[0] ? 0xFF : 0x00;
70  buf[2] = ledState[1] ? 0xFF : 0x00;
71  buf[3] = ledState[2] ? 0xFF : 0x00;
72  buf[4] = ledState[3] ? 0xFF : 0x00;
73  buf[5] = 0x00;
74  buf[6] = 0x00;
75 
76  PSBuzz_Command(buf, sizeof(buf));
77 };
78 
79 void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) {
80  // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
81  pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
82 };
Definition: usbhid.h:143
USB * pUsb
Definition: usbhid.h:145
void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
Definition: PSBuzz.cpp:23
void Reset()
Definition: PSBuzz.h:157
bool getButtonClick(ButtonEnum b, uint8_t controller=0)
Definition: PSBuzz.cpp:56
#define bmREQ_HID_OUT
Definition: usbhid.h:63
-
uint16_t VID
Definition: hiduniversal.h:69
+
EpInfo epInfo[totalEndpoints]
Definition: hidcomposite.h:63
uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t *dataptr, USBReadParser *p)
Definition: Usb.cpp:126
#define Notify(...)
Definition: message.h:51
@@ -80,13 +79,14 @@ $(function() {
#define PSBUZZ_PID
Definition: PSBuzz.h:25
uint8_t bAddress
Definition: usbhid.h:146
void setLedRaw(bool value, uint8_t controller=0)
Definition: PSBuzz.cpp:64
+
uint16_t PID
Definition: hidcomposite.h:71
#define PSTR(str)
#define MFK_CASTUINT8T
Definition: settings.h:194
+
uint16_t VID
Definition: hidcomposite.h:71
uint8_t OnInitSuccessful()
Definition: PSBuzz.cpp:41
void setLedOnAll()
Definition: PSBuzz.h:114
#define HID_REQUEST_SET_REPORT
Definition: usbhid.h:72
uint32_t val
Definition: PSBuzz.h:36
-
EpInfo epInfo[totalEndpoints]
Definition: hiduniversal.h:64
- - - - - + + + + + +
diff --git a/_p_s_buzz_8h__dep__incl.md5 b/_p_s_buzz_8h__dep__incl.md5 index 0d832b03..32256b63 100644 --- a/_p_s_buzz_8h__dep__incl.md5 +++ b/_p_s_buzz_8h__dep__incl.md5 @@ -1 +1 @@ -89fdce8c433f9f3ff883c438cb91a471 \ No newline at end of file +ee2c9f18aa05f25ebf0836629c2a7574 \ No newline at end of file diff --git a/_p_s_buzz_8h__incl.map b/_p_s_buzz_8h__incl.map index c566a41e..b5fbd9ce 100644 --- a/_p_s_buzz_8h__incl.map +++ b/_p_s_buzz_8h__incl.map @@ -1,7 +1,8 @@ - - - - - + + + + + + diff --git a/_p_s_buzz_8h__incl.md5 b/_p_s_buzz_8h__incl.md5 index 063dac97..c92a439b 100644 --- a/_p_s_buzz_8h__incl.md5 +++ b/_p_s_buzz_8h__incl.md5 @@ -1 +1 @@ -e9865eba6bb7dc48f5f354e4dc3ccb30 \ No newline at end of file +d8318015cdd7f05600be59fe22c9514b \ No newline at end of file diff --git a/_p_s_buzz_8h__incl.png b/_p_s_buzz_8h__incl.png index 0f5bf6c3..e36c04a0 100644 Binary files a/_p_s_buzz_8h__incl.png and b/_p_s_buzz_8h__incl.png differ diff --git a/_p_s_buzz_8h_source.html b/_p_s_buzz_8h_source.html index e5bf1b6e..4761be98 100644 --- a/_p_s_buzz_8h_source.html +++ b/_p_s_buzz_8h_source.html @@ -63,16 +63,15 @@ $(function() {
PSBuzz.h
-Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #ifndef _psbuzz_h_
19 #define _psbuzz_h_
20 
21 #include "hiduniversal.h"
22 #include "controllerEnums.h"
23 
24 #define PSBUZZ_VID 0x054C // Sony Corporation
25 #define PSBUZZ_PID 0x1000 // PS Buzz Controller
26 
29  struct {
30  uint8_t red : 1;
31  uint8_t yellow : 1;
32  uint8_t green : 1;
33  uint8_t orange : 1;
34  uint8_t blue : 1;
35  } __attribute__((packed)) btn[4];
36  uint32_t val : 20;
37 } __attribute__((packed));
38 
43 class PSBuzz : public HIDUniversal {
44 public:
49  PSBuzz(USB *p) :
50  HIDUniversal(p) {
51  Reset();
52  };
53 
58  bool connected() {
60  };
61 
66  void attachOnInit(void (*funcOnInit)(void)) {
67  pFuncOnInit = funcOnInit;
68  };
69 
82  bool getButtonPress(ButtonEnum b, uint8_t controller = 0);
83  bool getButtonClick(ButtonEnum b, uint8_t controller = 0);
95  void setLedRaw(bool value, uint8_t controller = 0);
96 
98  void setLedOffAll() {
99  for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
100  ledState[i] = false; // Just an easy way to set all four off at the same time
101  setLedRaw(false); // Turn the LED off, on all four controllers
102  };
103 
108  void setLedOff(uint8_t controller = 0) {
109  setLedRaw(false, controller);
110  };
111 
112 
114  void setLedOnAll() {
115  for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
116  ledState[i] = true; // Just an easy way to set all four off at the same time
117  setLedRaw(true); // Turn the LED on, on all four controllers
118  };
119 
124  void setLedOn(uint8_t controller = 0) {
125  setLedRaw(true, controller);
126  };
127 
132  void setLedToggle(uint8_t controller = 0) {
133  setLedRaw(!ledState[controller], controller);
134  };
137 protected:
146  void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
147 
153  uint8_t OnInitSuccessful();
157  void Reset() {
158  psbuzzButtons.val = 0;
159  oldButtonState.val = 0;
160  buttonClickState.val = 0;
161  for (uint8_t i = 0; i < sizeof(ledState); i++)
162  ledState[i] = 0;
163  };
164 
172  virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
173  return (vid == PSBUZZ_VID && pid == PSBUZZ_PID);
174  };
177 private:
178  void (*pFuncOnInit)(void); // Pointer to function called in onInit()
179 
180  void PSBuzz_Command(uint8_t *data, uint16_t nbytes);
181 
182  PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState;
183  bool ledState[4];
184 };
185 #endif
uint16_t PID
Definition: hiduniversal.h:69
-
Definition: usbhid.h:143
+Go to the documentation of this file.
1 /* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #ifndef _psbuzz_h_
19 #define _psbuzz_h_
20 
21 #include "hiduniversal.h"
22 #include "controllerEnums.h"
23 
24 #define PSBUZZ_VID 0x054C // Sony Corporation
25 #define PSBUZZ_PID 0x1000 // PS Buzz Controller
26 
29  struct {
30  uint8_t red : 1;
31  uint8_t yellow : 1;
32  uint8_t green : 1;
33  uint8_t orange : 1;
34  uint8_t blue : 1;
35  } __attribute__((packed)) btn[4];
36  uint32_t val : 20;
37 } __attribute__((packed));
38 
43 class PSBuzz : public HIDUniversal {
44 public:
49  PSBuzz(USB *p) :
50  HIDUniversal(p) {
51  Reset();
52  };
53 
58  bool connected() {
60  };
61 
66  void attachOnInit(void (*funcOnInit)(void)) {
67  pFuncOnInit = funcOnInit;
68  };
69 
82  bool getButtonPress(ButtonEnum b, uint8_t controller = 0);
83  bool getButtonClick(ButtonEnum b, uint8_t controller = 0);
95  void setLedRaw(bool value, uint8_t controller = 0);
96 
98  void setLedOffAll() {
99  for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
100  ledState[i] = false; // Just an easy way to set all four off at the same time
101  setLedRaw(false); // Turn the LED off, on all four controllers
102  };
103 
108  void setLedOff(uint8_t controller = 0) {
109  setLedRaw(false, controller);
110  };
111 
112 
114  void setLedOnAll() {
115  for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
116  ledState[i] = true; // Just an easy way to set all four off at the same time
117  setLedRaw(true); // Turn the LED on, on all four controllers
118  };
119 
124  void setLedOn(uint8_t controller = 0) {
125  setLedRaw(true, controller);
126  };
127 
132  void setLedToggle(uint8_t controller = 0) {
133  setLedRaw(!ledState[controller], controller);
134  };
137 protected:
146  void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
147 
153  uint8_t OnInitSuccessful();
157  void Reset() {
158  psbuzzButtons.val = 0;
159  oldButtonState.val = 0;
160  buttonClickState.val = 0;
161  for (uint8_t i = 0; i < sizeof(ledState); i++)
162  ledState[i] = 0;
163  };
164 
172  virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
173  return (vid == PSBUZZ_VID && pid == PSBUZZ_PID);
174  };
177 private:
178  void (*pFuncOnInit)(void); // Pointer to function called in onInit()
179 
180  void PSBuzz_Command(uint8_t *data, uint16_t nbytes);
181 
182  PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState;
183  bool ledState[4];
184 };
185 #endif
Definition: usbhid.h:143
uint8_t red
Definition: PSBuzz.h:30
+
struct PSBUZZButtons::@29 btn[4]
void setLedToggle(uint8_t controller=0)
Definition: PSBuzz.h:132
void attachOnInit(void(*funcOnInit)(void))
Definition: PSBuzz.h:66
-
virtual bool isReady()
Definition: hiduniversal.h:97
void Reset()
Definition: PSBuzz.h:157
+
virtual bool isReady()
Definition: hidcomposite.h:99
bool connected()
Definition: PSBuzz.h:58
uint8_t blue
Definition: PSBuzz.h:34
-
uint16_t VID
Definition: hiduniversal.h:69
uint8_t green
Definition: PSBuzz.h:32
@@ -81,10 +80,11 @@ $(function() {
ButtonEnum
#define PSBUZZ_PID
Definition: PSBuzz.h:25
uint8_t yellow
Definition: PSBuzz.h:31
+
uint16_t PID
Definition: hidcomposite.h:71
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid)
Definition: PSBuzz.h:172
void setLedOff(uint8_t controller=0)
Definition: PSBuzz.h:108
-
struct PSBUZZButtons::@31 btn[4]
+
uint16_t VID
Definition: hidcomposite.h:71
PSBuzz(USB *p)
Definition: PSBuzz.h:49
void setLedOnAll()
Definition: PSBuzz.h:114
Definition: UsbCore.h:210
@@ -92,7 +92,7 @@ $(function() {
uint32_t val
Definition: PSBuzz.h:36
uint8_t orange
Definition: PSBuzz.h:33
void setLedOffAll()
Definition: PSBuzz.h:98
- +
-Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9 
10 Contact information
11 -------------------
12 
13 Circuits At Home, LTD
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
16  */
17 /* USB functions */
18 
19 #include "Usb.h"
20 
21 static uint8_t usb_error = 0;
22 static uint8_t usb_task_state;
23 
24 /* constructor */
25 USB::USB() : bmHubPre(0) {
26  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
27  init();
28 }
29 
30 /* Initialize data structures */
31 void USB::init() {
32  //devConfigIndex = 0;
33  bmHubPre = 0;
34 }
35 
36 uint8_t USB::getUsbTaskState(void) {
37  return ( usb_task_state);
38 }
39 
40 void USB::setUsbTaskState(uint8_t state) {
41  usb_task_state = state;
42 }
43 
44 EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
45  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
46 
47  if(!p || !p->epinfo)
48  return NULL;
49 
50  EpInfo *pep = p->epinfo;
51 
52  for(uint8_t i = 0; i < p->epcount; i++) {
53  if((pep)->epAddr == ep)
54  return pep;
55 
56  pep++;
57  }
58  return NULL;
59 }
60 
61 /* set device table entry */
62 
63 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
64 uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
65  if(!eprecord_ptr)
67 
68  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
69 
70  if(!p)
72 
73  p->address.devAddress = addr;
74  p->epinfo = eprecord_ptr;
75  p->epcount = epcount;
76 
77  return 0;
78 }
79 
80 uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
81  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
82 
83  if(!p)
85 
86  if(!p->epinfo)
88 
89  *ppep = getEpInfoEntry(addr, ep);
90 
91  if(!*ppep)
93 
94  *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
95  (*nak_limit)--;
96  /*
97  USBTRACE2("\r\nAddress: ", addr);
98  USBTRACE2(" EP: ", ep);
99  USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
100  USBTRACE2(" NAK Limit: ", nak_limit);
101  USBTRACE("\r\n");
102  */
103  regWr(rPERADDR, addr); //set peripheral address
104 
105  uint8_t mode = regRd(rMODE);
106 
107  //Serial.print("\r\nMode: ");
108  //Serial.println( mode, HEX);
109  //Serial.print("\r\nLS: ");
110  //Serial.println(p->lowspeed, HEX);
111 
112 
113 
114  // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise
115  regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED));
116 
117  return 0;
118 }
119 
120 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
121 /* depending on request. Actual requests are defined as inlines */
122 /* return codes: */
123 /* 00 = success */
124 
125 /* 01-0f = non-zero HRSLT */
126 uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
127  uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
128  bool direction = false; //request direction, IN or OUT
129  uint8_t rcode;
130  SETUP_PKT setup_pkt;
131 
132  EpInfo *pep = NULL;
133  uint16_t nak_limit = 0;
134 
135  rcode = SetAddress(addr, ep, &pep, &nak_limit);
136 
137  if(rcode)
138  return rcode;
139 
140  direction = ((bmReqType & 0x80) > 0);
141 
142  /* fill in setup packet */
143  setup_pkt.ReqType_u.bmRequestType = bmReqType;
144  setup_pkt.bRequest = bRequest;
145  setup_pkt.wVal_u.wValueLo = wValLo;
146  setup_pkt.wVal_u.wValueHi = wValHi;
147  setup_pkt.wIndex = wInd;
148  setup_pkt.wLength = total;
149 
150  bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
151 
152  rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
153 
154  if(rcode) //return HRSLT if not zero
155  return ( rcode);
156 
157  if(dataptr != NULL) //data stage, if present
158  {
159  if(direction) //IN transfer
160  {
161  uint16_t left = total;
162 
163  pep->bmRcvToggle = 1; //bmRCVTOG1;
164 
165  while(left) {
166  // Bytes read into buffer
167 #if defined(ESP8266) || defined(ESP32)
168  yield(); // needed in order to reset the watchdog timer on the ESP8266
169 #endif
170  uint16_t read = nbytes;
171  //uint16_t read = (left<nbytes) ? left : nbytes;
172 
173  rcode = InTransfer(pep, nak_limit, &read, dataptr);
174  if(rcode == hrTOGERR) {
175  // yes, we flip it wrong here so that next time it is actually correct!
176  pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
177  continue;
178  }
179 
180  if(rcode)
181  return rcode;
182 
183  // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
184  if(!rcode && p)
185  ((USBReadParser*)p)->Parse(read, dataptr, total - left);
186 
187  left -= read;
188 
189  if(read < nbytes)
190  break;
191  }
192  } else //OUT transfer
193  {
194  pep->bmSndToggle = 1; //bmSNDTOG1;
195  rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
196  }
197  if(rcode) //return error
198  return ( rcode);
199  }
200  // Status stage
201  return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
202 }
203 
204 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
205 /* Keep sending INs and writes data to memory area pointed by 'data' */
206 
207 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
208  fe USB xfer timeout */
209 uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {
210  EpInfo *pep = NULL;
211  uint16_t nak_limit = 0;
212 
213  uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
214 
215  if(rcode) {
216  USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
217  USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
218  USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
219  return rcode;
220  }
221  return InTransfer(pep, nak_limit, nbytesptr, data, bInterval);
222 }
223 
224 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {
225  uint8_t rcode = 0;
226  uint8_t pktsize;
227 
228  uint16_t nbytes = *nbytesptr;
229  //printf("Requesting %i bytes ", nbytes);
230  uint8_t maxpktsize = pep->maxPktSize;
231 
232  *nbytesptr = 0;
233  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
234 
235  // use a 'break' to exit this loop
236  while(1) {
237 #if defined(ESP8266) || defined(ESP32)
238  yield(); // needed in order to reset the watchdog timer on the ESP8266
239 #endif
240  rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
241  if(rcode == hrTOGERR) {
242  // yes, we flip it wrong here so that next time it is actually correct!
243  pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;
244  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
245  continue;
246  }
247  if(rcode) {
248  //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
249  break; //should be 0, indicating ACK. Else return error code.
250  }
251  /* check for RCVDAVIRQ and generate error if not present
252  * the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred.
253  * Need to add handling for that
254  *
255  * NOTE: I've seen this happen with SPI corruption -- xxxajk
256  */
257  if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
258  //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
259  rcode = 0xf0; //receive error
260  break;
261  }
262  pktsize = regRd(rRCVBC); //number of received bytes
263  //printf("Got %i bytes \r\n", pktsize);
264  // This would be OK, but...
265  //assert(pktsize <= nbytes);
266  if(pktsize > nbytes) {
267  // This can happen. Use of assert on Arduino locks up the Arduino.
268  // So I will trim the value, and hope for the best.
269  //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
270  pktsize = nbytes;
271  }
272 
273  int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
274 
275  if(mem_left < 0)
276  mem_left = 0;
277 
278  data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
279 
280  regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
281  *nbytesptr += pktsize; // add this packet's byte count to total transfer length
282 
283  /* The transfer is complete under two conditions: */
284  /* 1. The device sent a short packet (L.T. maxPacketSize) */
285  /* 2. 'nbytes' have been transferred. */
286  if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
287  {
288  // Save toggle value
289  pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
290  //printf("\r\n");
291  rcode = 0;
292  break;
293  } else if(bInterval > 0)
294  delay(bInterval); // Delay according to polling interval
295  } //while( 1 )
296  return ( rcode);
297 }
298 
299 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
300 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
301 
302 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
303 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
304  EpInfo *pep = NULL;
305  uint16_t nak_limit = 0;
306 
307  uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
308 
309  if(rcode)
310  return rcode;
311 
312  return OutTransfer(pep, nak_limit, nbytes, data);
313 }
314 
315 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
316  uint8_t rcode = hrSUCCESS, retry_count;
317  uint8_t *data_p = data; //local copy of the data pointer
318  uint16_t bytes_tosend, nak_count;
319  uint16_t bytes_left = nbytes;
320 
321  uint8_t maxpktsize = pep->maxPktSize;
322 
323  if(maxpktsize < 1 || maxpktsize > 64)
325 
326  uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
327 
328  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
329 
330  while(bytes_left) {
331 #if defined(ESP8266) || defined(ESP32)
332  yield(); // needed in order to reset the watchdog timer on the ESP8266
333 #endif
334  retry_count = 0;
335  nak_count = 0;
336  bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
337  bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
338  regWr(rSNDBC, bytes_tosend); //set number of bytes
339  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
340  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)){
341 #if defined(ESP8266) || defined(ESP32)
342  yield(); // needed in order to reset the watchdog timer on the ESP8266
343 #endif
344  } //wait for the completion IRQ
345  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
346  rcode = (regRd(rHRSL) & 0x0f);
347 
348  while(rcode && ((int32_t)((uint32_t)millis() - timeout) < 0L)) {
349 #if defined(ESP8266) || defined(ESP32)
350  yield(); // needed in order to reset the watchdog timer on the ESP8266
351 #endif
352  switch(rcode) {
353  case hrNAK:
354  nak_count++;
355  if(nak_limit && (nak_count == nak_limit))
356  goto breakout;
357  //return ( rcode);
358  break;
359  case hrTIMEOUT:
360  retry_count++;
361  if(retry_count == USB_RETRY_LIMIT)
362  goto breakout;
363  //return ( rcode);
364  break;
365  case hrTOGERR:
366  // yes, we flip it wrong here so that next time it is actually correct!
367  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
368  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
369  break;
370  default:
371  goto breakout;
372  }//switch( rcode
373 
374  /* process NAK according to Host out NAK bug */
375  regWr(rSNDBC, 0);
376  regWr(rSNDFIFO, *data_p);
377  regWr(rSNDBC, bytes_tosend);
378  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
379  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)){
380 #if defined(ESP8266) || defined(ESP32)
381  yield(); // needed in order to reset the watchdog timer on the ESP8266
382 #endif
383  } //wait for the completion IRQ
384  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
385  rcode = (regRd(rHRSL) & 0x0f);
386  }//while( rcode && ....
387  bytes_left -= bytes_tosend;
388  data_p += bytes_tosend;
389  }//while( bytes_left...
390 breakout:
391 
392  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
393  return ( rcode); //should be 0 in all cases
394 }
395 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
396 /* If NAK, tries to re-send up to nak_limit times */
397 /* If nak_limit == 0, do not count NAKs, exit after timeout */
398 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
399 
400 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
401 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
402  uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
403  uint8_t tmpdata;
404  uint8_t rcode = hrSUCCESS;
405  uint8_t retry_count = 0;
406  uint16_t nak_count = 0;
407 
408  while((int32_t)((uint32_t)millis() - timeout) < 0L) {
409 #if defined(ESP8266) || defined(ESP32)
410  yield(); // needed in order to reset the watchdog timer on the ESP8266
411 #endif
412  regWr(rHXFR, (token | ep)); //launch the transfer
414 
415  while((int32_t)((uint32_t)millis() - timeout) < 0L) //wait for transfer completion
416  {
417 #if defined(ESP8266) || defined(ESP32)
418  yield(); // needed in order to reset the watchdog timer on the ESP8266
419 #endif
420  tmpdata = regRd(rHIRQ);
421 
422  if(tmpdata & bmHXFRDNIRQ) {
423  regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
424  rcode = 0x00;
425  break;
426  }//if( tmpdata & bmHXFRDNIRQ
427 
428  }//while ( millis() < timeout
429 
430  //if (rcode != 0x00) //exit if timeout
431  // return ( rcode);
432 
433  rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
434 
435  switch(rcode) {
436  case hrNAK:
437  nak_count++;
438  if(nak_limit && (nak_count == nak_limit))
439  return (rcode);
440  break;
441  case hrTIMEOUT:
442  retry_count++;
443  if(retry_count == USB_RETRY_LIMIT)
444  return (rcode);
445  break;
446  default:
447  return (rcode);
448  }//switch( rcode
449 
450  }//while( timeout > millis()
451  return ( rcode);
452 }
453 
454 /* USB main task. Performs enumeration/cleanup */
455 void USB::Task(void) //USB state machine
456 {
457  uint8_t rcode;
458  uint8_t tmpdata;
459  static uint32_t delay = 0;
460  //USB_DEVICE_DESCRIPTOR buf;
461  bool lowspeed = false;
462 
463  MAX3421E::Task();
464 
465  tmpdata = getVbusState();
466 
467  /* modify USB task state if Vbus changed */
468  switch(tmpdata) {
469  case SE1: //illegal state
470  usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
471  lowspeed = false;
472  break;
473  case SE0: //disconnected
474  if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
475  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
476  lowspeed = false;
477  break;
478  case LSHOST:
479 
480  lowspeed = true;
481  //intentional fallthrough
482  case FSHOST: //attached
483  if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
484  delay = (uint32_t)millis() + USB_SETTLE_DELAY;
485  usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
486  }
487  break;
488  }// switch( tmpdata
489 
490  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
491  if(devConfig[i])
492  rcode = devConfig[i]->Poll();
493 
494  switch(usb_task_state) {
496  init();
497 
498  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
499  if(devConfig[i])
500  rcode = devConfig[i]->Release();
501 
502  usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
503  break;
504  case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
505  break;
506  case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
507  break;
508  case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
509  if((int32_t)((uint32_t)millis() - delay) >= 0L)
510  usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
511  else break; // don't fall through
513  regWr(rHCTL, bmBUSRST); //issue bus reset
515  break;
517  if((regRd(rHCTL) & bmBUSRST) == 0) {
518  tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
519  regWr(rMODE, tmpdata);
520  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
521  //delay = (uint32_t)millis() + 20; //20ms wait after reset per USB spec
522  }
523  break;
524  case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
525  if(regRd(rHIRQ) & bmFRAMEIRQ) {
526  //when first SOF received _and_ 20ms has passed we can continue
527  /*
528  if (delay < (uint32_t)millis()) //20ms passed
529  usb_task_state = USB_STATE_CONFIGURING;
530  */
531  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
532  delay = (uint32_t)millis() + 20;
533  }
534  break;
536  if((int32_t)((uint32_t)millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
537  else break; // don't fall through
539 
540  //Serial.print("\r\nConf.LS: ");
541  //Serial.println(lowspeed, HEX);
542 
543  rcode = Configuring(0, 0, lowspeed);
544 
545  if(rcode) {
547  usb_error = rcode;
548  usb_task_state = USB_STATE_ERROR;
549  }
550  } else
551  usb_task_state = USB_STATE_RUNNING;
552  break;
553  case USB_STATE_RUNNING:
554  break;
555  case USB_STATE_ERROR:
556  //MAX3421E::Init();
557  break;
558  } // switch( usb_task_state )
559 }
560 
561 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
562  //uint8_t buf[12];
563  uint8_t rcode;
564  UsbDevice *p0 = NULL, *p = NULL;
565 
566  // Get pointer to pseudo device with address 0 assigned
567  p0 = addrPool.GetUsbDevicePtr(0);
568 
569  if(!p0)
571 
572  if(!p0->epinfo)
574 
575  p0->lowspeed = (lowspeed) ? true : false;
576 
577  // Allocate new address according to device class
578  uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
579 
580  if(!bAddress)
582 
583  p = addrPool.GetUsbDevicePtr(bAddress);
584 
585  if(!p)
587 
588  p->lowspeed = lowspeed;
589 
590  // Assign new address to the device
591  rcode = setAddr(0, 0, bAddress);
592 
593  if(rcode) {
594  addrPool.FreeAddress(bAddress);
595  bAddress = 0;
596  return rcode;
597  }
598  return 0;
599 };
600 
601 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
602  //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
603  uint8_t retries = 0;
604 
605 again:
606  uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
608  if(parent == 0) {
609  // Send a bus reset on the root interface.
610  regWr(rHCTL, bmBUSRST); //issue bus reset
611  delay(102); // delay 102ms, compensate for clock inaccuracy.
612  } else {
613  // reset parent port
614  devConfig[parent]->ResetHubPort(port);
615  }
616  } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
617  delay(100);
618  retries++;
619  goto again;
620  } else if(rcode)
621  return rcode;
622 
623  rcode = devConfig[driver]->Init(parent, port, lowspeed);
624  if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
625  delay(100);
626  retries++;
627  goto again;
628  }
629  if(rcode) {
630  // Issue a bus reset, because the device may be in a limbo state
631  if(parent == 0) {
632  // Send a bus reset on the root interface.
633  regWr(rHCTL, bmBUSRST); //issue bus reset
634  delay(102); // delay 102ms, compensate for clock inaccuracy.
635  } else {
636  // reset parent port
637  devConfig[parent]->ResetHubPort(port);
638  }
639  }
640  return rcode;
641 }
642 
643 /*
644  * This is broken. We need to enumerate differently.
645  * It causes major problems with several devices if detected in an unexpected order.
646  *
647  *
648  * Oleg - I wouldn't do anything before the newly connected device is considered sane.
649  * i.e.(delays are not indicated for brevity):
650  * 1. reset
651  * 2. GetDevDescr();
652  * 3a. If ACK, continue with allocating address, addressing, etc.
653  * 3b. Else reset again, count resets, stop at some number (5?).
654  * 4. When max.number of resets is reached, toggle power/fail
655  * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
656  * it doesn't need to be reset again
657  * New steps proposal:
658  * 1: get address pool instance. exit on fail
659  * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
660  * 3: bus reset, 100ms delay
661  * 4: set address
662  * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
663  * 6: while (configurations) {
664  * for(each configuration) {
665  * for (each driver) {
666  * 6a: Ask device if it likes configuration. Returns 0 on OK.
667  * If successful, the driver configured device.
668  * The driver now owns the endpoints, and takes over managing them.
669  * The following will need codes:
670  * Everything went well, instance consumed, exit with success.
671  * Instance already in use, ignore it, try next driver.
672  * Not a supported device, ignore it, try next driver.
673  * Not a supported configuration for this device, ignore it, try next driver.
674  * Could not configure device, fatal, exit with fail.
675  * }
676  * }
677  * }
678  * 7: for(each driver) {
679  * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
680  * 8: if we get here, no driver likes the device plugged in, so exit failure.
681  *
682  */
683 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
684  //uint8_t bAddress = 0;
685  //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
686  uint8_t devConfigIndex;
687  uint8_t rcode = 0;
688  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
689  USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
690  UsbDevice *p = NULL;
691  EpInfo *oldep_ptr = NULL;
692  EpInfo epInfo;
693 
694  epInfo.epAddr = 0;
695  epInfo.maxPktSize = 8;
696  epInfo.bmSndToggle = 0;
697  epInfo.bmRcvToggle = 0;
698  epInfo.bmNakPower = USB_NAK_MAX_POWER;
699 
700  //delay(2000);
701  AddressPool &addrPool = GetAddressPool();
702  // Get pointer to pseudo device with address 0 assigned
703  p = addrPool.GetUsbDevicePtr(0);
704  if(!p) {
705  //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
707  }
708 
709  // Save old pointer to EP_RECORD of address 0
710  oldep_ptr = p->epinfo;
711 
712  // Temporary assign new pointer to epInfo to p->epinfo in order to
713  // avoid toggle inconsistence
714 
715  p->epinfo = &epInfo;
716 
717  p->lowspeed = lowspeed;
718  // Get device descriptor
719  rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
720 
721  // Restore p->epinfo
722  p->epinfo = oldep_ptr;
723 
724  if(rcode) {
725  //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
726  return rcode;
727  }
728 
729  // to-do?
730  // Allocate new address according to device class
731  //bAddress = addrPool.AllocAddress(parent, false, port);
732 
733  uint16_t vid = udd->idVendor;
734  uint16_t pid = udd->idProduct;
735  uint8_t klass = udd->bDeviceClass;
736  uint8_t subklass = udd->bDeviceSubClass;
737  // Attempt to configure if VID/PID or device class matches with a driver
738  // Qualify with subclass too.
739  //
740  // VID/PID & class tests default to false for drivers not yet ported
741  // subclass defaults to true, so you don't have to define it if you don't have to.
742  //
743  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
744  if(!devConfig[devConfigIndex]) continue; // no driver
745  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
746  if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
747  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
749  break;
750  }
751  }
752 
753  if(devConfigIndex < USB_NUMDEVICES) {
754  return rcode;
755  }
756 
757 
758  // blindly attempt to configure
759  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
760  if(!devConfig[devConfigIndex]) continue;
761  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
762  if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
763  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
764 
765  //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
767  // in case of an error dev_index should be reset to 0
768  // in order to start from the very beginning the
769  // next time the program gets here
770  //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
771  // devConfigIndex = 0;
772  return rcode;
773  }
774  }
775  // if we get here that means that the device class is not supported by any of registered classes
776  rcode = DefaultAddressing(parent, port, lowspeed);
777 
778  return rcode;
779 }
780 
781 uint8_t USB::ReleaseDevice(uint8_t addr) {
782  if(!addr)
783  return 0;
784 
785  for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
786  if(!devConfig[i]) continue;
787  if(devConfig[i]->GetAddress() == addr)
788  return devConfig[i]->Release();
789  }
790  return 0;
791 }
792 
793 #if 1
794 //get device descriptor
795 
796 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
797  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
798 }
799 //get configuration descriptor
800 
801 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
802  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
803 }
804 
805 /* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
806  total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */
807 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
808  const uint8_t bufSize = 64;
809  uint8_t buf[bufSize];
810  USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
811 
812  uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
813 
814  if(ret)
815  return ret;
816 
817  uint16_t total = ucd->wTotalLength;
818 
819  //USBTRACE2("\r\ntotal conf.size:", total);
820 
821  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
822 }
823 
824 //get string descriptor
825 
826 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
827  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
828 }
829 //set address
830 
831 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
832  uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
833  //delay(2); //per USB 2.0 sect.9.2.6.3
834  delay(300); // Older spec says you should wait at least 200ms
835  return rcode;
836  //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
837 }
838 //set configuration
839 
840 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
841  return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
842 }
843 
844 #endif // defined(USB_METHODS_INLINE)
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:801
+Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9 
10 Contact information
11 -------------------
12 
13 Circuits At Home, LTD
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
16  */
17 /* USB functions */
18 
19 #include "Usb.h"
20 
21 static uint8_t usb_error = 0;
22 static uint8_t usb_task_state;
23 
24 /* constructor */
25 USB::USB() : bmHubPre(0) {
26  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
27  init();
28 }
29 
30 /* Initialize data structures */
31 void USB::init() {
32  //devConfigIndex = 0;
33  bmHubPre = 0;
34 }
35 
36 uint8_t USB::getUsbTaskState(void) {
37  return ( usb_task_state);
38 }
39 
40 void USB::setUsbTaskState(uint8_t state) {
41  usb_task_state = state;
42 }
43 
44 EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
45  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
46 
47  if(!p || !p->epinfo)
48  return NULL;
49 
50  EpInfo *pep = p->epinfo;
51 
52  for(uint8_t i = 0; i < p->epcount; i++) {
53  if((pep)->epAddr == ep)
54  return pep;
55 
56  pep++;
57  }
58  return NULL;
59 }
60 
61 /* set device table entry */
62 
63 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
64 uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
65  if(!eprecord_ptr)
67 
68  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
69 
70  if(!p)
72 
73  p->address.devAddress = addr;
74  p->epinfo = eprecord_ptr;
75  p->epcount = epcount;
76 
77  return 0;
78 }
79 
80 uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
81  UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
82 
83  if(!p)
85 
86  if(!p->epinfo)
88 
89  *ppep = getEpInfoEntry(addr, ep);
90 
91  if(!*ppep)
93 
94  *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
95  (*nak_limit)--;
96  /*
97  USBTRACE2("\r\nAddress: ", addr);
98  USBTRACE2(" EP: ", ep);
99  USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
100  USBTRACE2(" NAK Limit: ", nak_limit);
101  USBTRACE("\r\n");
102  */
103  regWr(rPERADDR, addr); //set peripheral address
104 
105  uint8_t mode = regRd(rMODE);
106 
107  //Serial.print("\r\nMode: ");
108  //Serial.println( mode, HEX);
109  //Serial.print("\r\nLS: ");
110  //Serial.println(p->lowspeed, HEX);
111 
112 
113 
114  // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise
115  regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED));
116 
117  return 0;
118 }
119 
120 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
121 /* depending on request. Actual requests are defined as inlines */
122 /* return codes: */
123 /* 00 = success */
124 
125 /* 01-0f = non-zero HRSLT */
126 uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
127  uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
128  bool direction = false; //request direction, IN or OUT
129  uint8_t rcode;
130  SETUP_PKT setup_pkt;
131 
132  EpInfo *pep = NULL;
133  uint16_t nak_limit = 0;
134 
135  rcode = SetAddress(addr, ep, &pep, &nak_limit);
136 
137  if(rcode)
138  return rcode;
139 
140  direction = ((bmReqType & 0x80) > 0);
141 
142  /* fill in setup packet */
143  setup_pkt.ReqType_u.bmRequestType = bmReqType;
144  setup_pkt.bRequest = bRequest;
145  setup_pkt.wVal_u.wValueLo = wValLo;
146  setup_pkt.wVal_u.wValueHi = wValHi;
147  setup_pkt.wIndex = wInd;
148  setup_pkt.wLength = total;
149 
150  bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
151 
152  rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
153 
154  if(rcode) //return HRSLT if not zero
155  return ( rcode);
156 
157  if(dataptr != NULL) //data stage, if present
158  {
159  if(direction) //IN transfer
160  {
161  uint16_t left = total;
162 
163  pep->bmRcvToggle = 1; //bmRCVTOG1;
164 
165  while(left) {
166  // Bytes read into buffer
167 #if defined(ESP8266) || defined(ESP32)
168  yield(); // needed in order to reset the watchdog timer on the ESP8266
169 #endif
170  uint16_t read = nbytes;
171  //uint16_t read = (left<nbytes) ? left : nbytes;
172 
173  rcode = InTransfer(pep, nak_limit, &read, dataptr);
174  if(rcode == hrTOGERR) {
175  // yes, we flip it wrong here so that next time it is actually correct!
176  pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
177  continue;
178  }
179 
180  if(rcode)
181  return rcode;
182 
183  // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
184  if(!rcode && p)
185  ((USBReadParser*)p)->Parse(read, dataptr, total - left);
186 
187  left -= read;
188 
189  if(read < nbytes)
190  break;
191  }
192  } else //OUT transfer
193  {
194  pep->bmSndToggle = 1; //bmSNDTOG1;
195  rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
196  }
197  if(rcode) //return error
198  return ( rcode);
199  }
200  // Status stage
201  return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
202 }
203 
204 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
205 /* Keep sending INs and writes data to memory area pointed by 'data' */
206 
207 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
208  fe USB xfer timeout */
209 uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {
210  EpInfo *pep = NULL;
211  uint16_t nak_limit = 0;
212 
213  uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
214 
215  if(rcode) {
216  USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
217  USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
218  USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
219  return rcode;
220  }
221  return InTransfer(pep, nak_limit, nbytesptr, data, bInterval);
222 }
223 
224 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {
225  uint8_t rcode = 0;
226  uint8_t pktsize;
227 
228  uint16_t nbytes = *nbytesptr;
229  //printf("Requesting %i bytes ", nbytes);
230  uint8_t maxpktsize = pep->maxPktSize;
231 
232  *nbytesptr = 0;
233  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
234 
235  // use a 'break' to exit this loop
236  while(1) {
237 #if defined(ESP8266) || defined(ESP32)
238  yield(); // needed in order to reset the watchdog timer on the ESP8266
239 #endif
240  rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
241  if(rcode == hrTOGERR) {
242  // yes, we flip it wrong here so that next time it is actually correct!
243  pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;
244  regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
245  continue;
246  }
247  if(rcode) {
248  //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
249  break; //should be 0, indicating ACK. Else return error code.
250  }
251  /* check for RCVDAVIRQ and generate error if not present
252  * the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred.
253  * Need to add handling for that
254  *
255  * NOTE: I've seen this happen with SPI corruption -- xxxajk
256  */
257  if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
258  //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
259  rcode = 0xf0; //receive error
260  break;
261  }
262  pktsize = regRd(rRCVBC); //number of received bytes
263  //printf("Got %i bytes \r\n", pktsize);
264  // This would be OK, but...
265  //assert(pktsize <= nbytes);
266  if(pktsize > nbytes) {
267  // This can happen. Use of assert on Arduino locks up the Arduino.
268  // So I will trim the value, and hope for the best.
269  //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
270  pktsize = nbytes;
271  }
272 
273  int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
274 
275  if(mem_left < 0)
276  mem_left = 0;
277 
278  data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
279 
280  regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
281  *nbytesptr += pktsize; // add this packet's byte count to total transfer length
282 
283  /* The transfer is complete under two conditions: */
284  /* 1. The device sent a short packet (L.T. maxPacketSize) */
285  /* 2. 'nbytes' have been transferred. */
286  if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
287  {
288  // Save toggle value
289  pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
290  //printf("\r\n");
291  rcode = 0;
292  break;
293  } else if(bInterval > 0)
294  delay(bInterval); // Delay according to polling interval
295  } //while( 1 )
296  return ( rcode);
297 }
298 
299 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
300 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
301 
302 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
303 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
304  EpInfo *pep = NULL;
305  uint16_t nak_limit = 0;
306 
307  uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
308 
309  if(rcode)
310  return rcode;
311 
312  return OutTransfer(pep, nak_limit, nbytes, data);
313 }
314 
315 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
316  uint8_t rcode = hrSUCCESS, retry_count;
317  uint8_t *data_p = data; //local copy of the data pointer
318  uint16_t bytes_tosend, nak_count;
319  uint16_t bytes_left = nbytes;
320 
321  uint8_t maxpktsize = pep->maxPktSize;
322 
323  if(maxpktsize < 1 || maxpktsize > 64)
325 
326  uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
327 
328  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
329 
330  while(bytes_left) {
331 #if defined(ESP8266) || defined(ESP32)
332  yield(); // needed in order to reset the watchdog timer on the ESP8266
333 #endif
334  retry_count = 0;
335  nak_count = 0;
336  bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
337  bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
338  regWr(rSNDBC, bytes_tosend); //set number of bytes
339  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
340  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)){
341 #if defined(ESP8266) || defined(ESP32)
342  yield(); // needed in order to reset the watchdog timer on the ESP8266
343 #endif
344  } //wait for the completion IRQ
345  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
346  rcode = (regRd(rHRSL) & 0x0f);
347 
348  while(rcode && ((int32_t)((uint32_t)millis() - timeout) < 0L)) {
349 #if defined(ESP8266) || defined(ESP32)
350  yield(); // needed in order to reset the watchdog timer on the ESP8266
351 #endif
352  switch(rcode) {
353  case hrNAK:
354  nak_count++;
355  if(nak_limit && (nak_count == nak_limit))
356  goto breakout;
357  //return ( rcode);
358  break;
359  case hrTIMEOUT:
360  retry_count++;
361  if(retry_count == USB_RETRY_LIMIT)
362  goto breakout;
363  //return ( rcode);
364  break;
365  case hrTOGERR:
366  // yes, we flip it wrong here so that next time it is actually correct!
367  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
368  regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
369  break;
370  default:
371  goto breakout;
372  }//switch( rcode
373 
374  /* process NAK according to Host out NAK bug */
375  regWr(rSNDBC, 0);
376  regWr(rSNDFIFO, *data_p);
377  regWr(rSNDBC, bytes_tosend);
378  regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
379  while(!(regRd(rHIRQ) & bmHXFRDNIRQ)){
380 #if defined(ESP8266) || defined(ESP32)
381  yield(); // needed in order to reset the watchdog timer on the ESP8266
382 #endif
383  } //wait for the completion IRQ
384  regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
385  rcode = (regRd(rHRSL) & 0x0f);
386  }//while( rcode && ....
387  bytes_left -= bytes_tosend;
388  data_p += bytes_tosend;
389  }//while( bytes_left...
390 breakout:
391 
392  pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
393  return ( rcode); //should be 0 in all cases
394 }
395 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
396 /* If NAK, tries to re-send up to nak_limit times */
397 /* If nak_limit == 0, do not count NAKs, exit after timeout */
398 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
399 
400 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
401 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
402  uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
403  uint8_t tmpdata;
404  uint8_t rcode = hrSUCCESS;
405  uint8_t retry_count = 0;
406  uint16_t nak_count = 0;
407 
408  while((int32_t)((uint32_t)millis() - timeout) < 0L) {
409 #if defined(ESP8266) || defined(ESP32)
410  yield(); // needed in order to reset the watchdog timer on the ESP8266
411 #endif
412  regWr(rHXFR, (token | ep)); //launch the transfer
414 
415  while((int32_t)((uint32_t)millis() - timeout) < 0L) //wait for transfer completion
416  {
417 #if defined(ESP8266) || defined(ESP32)
418  yield(); // needed in order to reset the watchdog timer on the ESP8266
419 #endif
420  tmpdata = regRd(rHIRQ);
421 
422  if(tmpdata & bmHXFRDNIRQ) {
423  regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
424  rcode = 0x00;
425  break;
426  }//if( tmpdata & bmHXFRDNIRQ
427 
428  }//while ( millis() < timeout
429 
430  //if (rcode != 0x00) //exit if timeout
431  // return ( rcode);
432 
433  rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
434 
435  switch(rcode) {
436  case hrNAK:
437  nak_count++;
438  if(nak_limit && (nak_count == nak_limit))
439  return (rcode);
440  break;
441  case hrTIMEOUT:
442  retry_count++;
443  if(retry_count == USB_RETRY_LIMIT)
444  return (rcode);
445  break;
446  default:
447  return (rcode);
448  }//switch( rcode
449 
450  }//while( timeout > millis()
451  return ( rcode);
452 }
453 
454 /* USB main task. Performs enumeration/cleanup */
455 void USB::Task(void) //USB state machine
456 {
457  uint8_t rcode;
458  uint8_t tmpdata;
459  static uint32_t delay = 0;
460  //USB_DEVICE_DESCRIPTOR buf;
461  bool lowspeed = false;
462 
463  MAX3421E::Task();
464 
465  tmpdata = getVbusState();
466 
467  /* modify USB task state if Vbus changed */
468  switch(tmpdata) {
469  case SE1: //illegal state
470  usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
471  lowspeed = false;
472  break;
473  case SE0: //disconnected
474  if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
475  usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
476  lowspeed = false;
477  break;
478  case LSHOST:
479 
480  lowspeed = true;
481  //intentional fallthrough
482  case FSHOST: //attached
483  if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
484  delay = (uint32_t)millis() + USB_SETTLE_DELAY;
485  usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
486  }
487  break;
488  }// switch( tmpdata
489 
490  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
491  if(devConfig[i])
492  rcode = devConfig[i]->Poll();
493 
494  switch(usb_task_state) {
496  init();
497 
498  for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
499  if(devConfig[i])
500  rcode = devConfig[i]->Release();
501 
502  usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
503  break;
504  case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
505  break;
506  case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
507  break;
508  case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
509  if((int32_t)((uint32_t)millis() - delay) >= 0L)
510  usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
511  else break; // don't fall through
513  regWr(rHCTL, bmBUSRST); //issue bus reset
515  break;
517  if((regRd(rHCTL) & bmBUSRST) == 0) {
518  tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
519  regWr(rMODE, tmpdata);
520  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
521  //delay = (uint32_t)millis() + 20; //20ms wait after reset per USB spec
522  }
523  break;
524  case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
525  if(regRd(rHIRQ) & bmFRAMEIRQ) {
526  //when first SOF received _and_ 20ms has passed we can continue
527  /*
528  if (delay < (uint32_t)millis()) //20ms passed
529  usb_task_state = USB_STATE_CONFIGURING;
530  */
531  usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
532  delay = (uint32_t)millis() + 20;
533  }
534  break;
536  if((int32_t)((uint32_t)millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
537  else break; // don't fall through
539 
540  //Serial.print("\r\nConf.LS: ");
541  //Serial.println(lowspeed, HEX);
542 
543  rcode = Configuring(0, 0, lowspeed);
544 
545  if(rcode) {
547  usb_error = rcode;
548  usb_task_state = USB_STATE_ERROR;
549  }
550  } else
551  usb_task_state = USB_STATE_RUNNING;
552  break;
553  case USB_STATE_RUNNING:
554  break;
555  case USB_STATE_ERROR:
556  //MAX3421E::Init();
557  break;
558  } // switch( usb_task_state )
559 }
560 
561 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
562  //uint8_t buf[12];
563  uint8_t rcode;
564  UsbDevice *p0 = NULL, *p = NULL;
565 
566  // Get pointer to pseudo device with address 0 assigned
567  p0 = addrPool.GetUsbDevicePtr(0);
568 
569  if(!p0)
571 
572  if(!p0->epinfo)
574 
575  p0->lowspeed = (lowspeed) ? true : false;
576 
577  // Allocate new address according to device class
578  uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
579 
580  if(!bAddress)
582 
583  p = addrPool.GetUsbDevicePtr(bAddress);
584 
585  if(!p)
587 
588  p->lowspeed = lowspeed;
589 
590  // Assign new address to the device
591  rcode = setAddr(0, 0, bAddress);
592 
593  if(rcode) {
594  addrPool.FreeAddress(bAddress);
595  bAddress = 0;
596  return rcode;
597  }
598  return 0;
599 };
600 
601 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
602  //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
603  uint8_t retries = 0;
604 
605 again:
606  uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
608  if(parent == 0) {
609  // Send a bus reset on the root interface.
610  regWr(rHCTL, bmBUSRST); //issue bus reset
611  delay(102); // delay 102ms, compensate for clock inaccuracy.
612  } else {
613  // reset parent port
614  devConfig[parent]->ResetHubPort(port);
615  }
616  } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
617  delay(100);
618  retries++;
619  goto again;
620  } else if(rcode)
621  return rcode;
622 
623  rcode = devConfig[driver]->Init(parent, port, lowspeed);
624  if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
625  delay(100);
626  retries++;
627  goto again;
628  }
629  if(rcode) {
630  // Issue a bus reset, because the device may be in a limbo state
631  if(parent == 0) {
632  // Send a bus reset on the root interface.
633  regWr(rHCTL, bmBUSRST); //issue bus reset
634  delay(102); // delay 102ms, compensate for clock inaccuracy.
635  } else {
636  // reset parent port
637  devConfig[parent]->ResetHubPort(port);
638  }
639  }
640  return rcode;
641 }
642 
643 /*
644  * This is broken. We need to enumerate differently.
645  * It causes major problems with several devices if detected in an unexpected order.
646  *
647  *
648  * Oleg - I wouldn't do anything before the newly connected device is considered sane.
649  * i.e.(delays are not indicated for brevity):
650  * 1. reset
651  * 2. GetDevDescr();
652  * 3a. If ACK, continue with allocating address, addressing, etc.
653  * 3b. Else reset again, count resets, stop at some number (5?).
654  * 4. When max.number of resets is reached, toggle power/fail
655  * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
656  * it doesn't need to be reset again
657  * New steps proposal:
658  * 1: get address pool instance. exit on fail
659  * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
660  * 3: bus reset, 100ms delay
661  * 4: set address
662  * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
663  * 6: while (configurations) {
664  * for(each configuration) {
665  * for (each driver) {
666  * 6a: Ask device if it likes configuration. Returns 0 on OK.
667  * If successful, the driver configured device.
668  * The driver now owns the endpoints, and takes over managing them.
669  * The following will need codes:
670  * Everything went well, instance consumed, exit with success.
671  * Instance already in use, ignore it, try next driver.
672  * Not a supported device, ignore it, try next driver.
673  * Not a supported configuration for this device, ignore it, try next driver.
674  * Could not configure device, fatal, exit with fail.
675  * }
676  * }
677  * }
678  * 7: for(each driver) {
679  * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
680  * 8: if we get here, no driver likes the device plugged in, so exit failure.
681  *
682  */
683 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
684  //uint8_t bAddress = 0;
685  //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
686  uint8_t devConfigIndex;
687  uint8_t rcode = 0;
688  uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
689  USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
690  UsbDevice *p = NULL;
691  EpInfo *oldep_ptr = NULL;
692  EpInfo epInfo;
693 
694  epInfo.epAddr = 0;
695  epInfo.maxPktSize = 8;
696  epInfo.bmSndToggle = 0;
697  epInfo.bmRcvToggle = 0;
698  epInfo.bmNakPower = USB_NAK_MAX_POWER;
699 
700  //delay(2000);
701  AddressPool &addrPool = GetAddressPool();
702  // Get pointer to pseudo device with address 0 assigned
703  p = addrPool.GetUsbDevicePtr(0);
704  if(!p) {
705  //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
707  }
708 
709  // Save old pointer to EP_RECORD of address 0
710  oldep_ptr = p->epinfo;
711 
712  // Temporary assign new pointer to epInfo to p->epinfo in order to
713  // avoid toggle inconsistence
714 
715  p->epinfo = &epInfo;
716 
717  p->lowspeed = lowspeed;
718  // Get device descriptor
719  rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
720 
721  // Restore p->epinfo
722  p->epinfo = oldep_ptr;
723 
724  if(rcode) {
725  //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
726  return rcode;
727  }
728 
729  // to-do?
730  // Allocate new address according to device class
731  //bAddress = addrPool.AllocAddress(parent, false, port);
732 
733  uint16_t vid = udd->idVendor;
734  uint16_t pid = udd->idProduct;
735  uint8_t klass = udd->bDeviceClass;
736  uint8_t subklass = udd->bDeviceSubClass;
737  // Attempt to configure if VID/PID or device class matches with a driver
738  // Qualify with subclass too.
739  //
740  // VID/PID & class tests default to false for drivers not yet ported
741  // subclass defaults to true, so you don't have to define it if you don't have to.
742  //
743  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
744  if(!devConfig[devConfigIndex]) continue; // no driver
745  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
746  if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
747  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
749  break;
750  }
751  }
752 
753  if(devConfigIndex < USB_NUMDEVICES) {
754  return rcode;
755  }
756 
757 
758  // blindly attempt to configure
759  for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
760  if(!devConfig[devConfigIndex]) continue;
761  if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
762  if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
763  rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
764 
765  //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
767  // in case of an error dev_index should be reset to 0
768  // in order to start from the very beginning the
769  // next time the program gets here
770  //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
771  // devConfigIndex = 0;
772  return rcode;
773  }
774  }
775  // if we get here that means that the device class is not supported by any of registered classes
776  rcode = DefaultAddressing(parent, port, lowspeed);
777 
778  return rcode;
779 }
780 
781 uint8_t USB::ReleaseDevice(uint8_t addr) {
782  if(!addr)
783  return 0;
784 
785  for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
786  if(!devConfig[i]) continue;
787  if(devConfig[i]->GetAddress() == addr)
788  return devConfig[i]->Release();
789  }
790  return 0;
791 }
792 
793 #if 1
794 //get device descriptor
795 
796 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
797  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
798 }
799 //get configuration descriptor
800 
801 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
802  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
803 }
804 
805 /* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
806  total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */
807 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
808  const uint8_t bufSize = 64;
809  uint8_t buf[bufSize];
810  USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
811 
812  uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
813 
814  if(ret)
815  return ret;
816 
817  uint16_t total = ucd->wTotalLength;
818 
819  //USBTRACE2("\r\ntotal conf.size:", total);
820 
821  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
822 }
823 
824 //get string descriptor
825 
826 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
827  return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
828 }
829 //set address
830 
831 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
832  uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
833  //delay(2); //per USB 2.0 sect.9.2.6.3
834  delay(300); // Older spec says you should wait at least 200ms
835  return rcode;
836  //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
837 }
838 //set configuration
839 
840 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
841  return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
842 }
843 
844 #endif // defined(USB_METHODS_INLINE)
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
virtual uint8_t Poll()
Definition: UsbCore.h:149
@@ -72,6 +72,7 @@ $(function() {
#define USB_ATTACHED_SUBSTATE_WAIT_RESET
Definition: UsbCore.h:127
#define FSHOST
Definition: max3421e.h:37
#define rHCTL
Definition: max3421e.h:181
+
union SETUP_PKT::@31 wVal_u
EpInfo * epinfo
Definition: address.h:83
bool lowspeed
Definition: address.h:86
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:96
@@ -123,7 +124,6 @@ $(function() {
#define tokIN
Definition: max3421e.h:196
#define LSHOST
Definition: max3421e.h:38
#define USB_XFER_TIMEOUT
Definition: UsbCore.h:107
-
union SETUP_PKT::@33 wVal_u
Definition: address.h:39
#define rMODE
Definition: max3421e.h:167
void setUsbTaskState(uint8_t state)
Definition: Usb.cpp:40
@@ -155,6 +155,7 @@ $(function() {
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:95
#define USB_STATE_MASK
Definition: UsbCore.h:117
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:90
+
union SETUP_PKT::@30 ReqType_u
void Task(void)
Definition: Usb.cpp:455
#define USB_DETACHED_SUBSTATE_ILLEGAL
Definition: UsbCore.h:122
#define hrTIMEOUT
Definition: max3421e.h:228
@@ -175,7 +176,6 @@ $(function() {
AddressPool & GetAddressPool()
Definition: UsbCore.h:226
#define USB_ERROR_INVALID_ARGUMENT
Definition: UsbCore.h:97
uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed)
Definition: Usb.cpp:683
-
union SETUP_PKT::@32 ReqType_u
#define USBTRACE3(s, r, l)
Definition: macros.h:85
uint8_t bRequest
Definition: UsbCore.h:187
#define SE0
Definition: max3421e.h:35
diff --git a/_usb_8h.html b/_usb_8h.html index e5cb4866..8d834f9b 100644 --- a/_usb_8h.html +++ b/_usb_8h.html @@ -68,55 +68,55 @@ This graph shows which files directly or indirectly include this file:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/_usb_8h__dep__incl.map b/_usb_8h__dep__incl.map index e877db15..81721e44 100644 --- a/_usb_8h__dep__incl.map +++ b/_usb_8h__dep__incl.map @@ -1,51 +1,51 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_usb_8h__dep__incl.md5 b/_usb_8h__dep__incl.md5 index 1127a03e..9ba6286c 100644 --- a/_usb_8h__dep__incl.md5 +++ b/_usb_8h__dep__incl.md5 @@ -1 +1 @@ -c3d178c87de440befcdfa627a34aac33 \ No newline at end of file +7630a82c45bf91c05f165eb324a51752 \ No newline at end of file diff --git a/_usb_8h__dep__incl.png b/_usb_8h__dep__incl.png index 4559da81..fc1043e5 100644 Binary files a/_usb_8h__dep__incl.png and b/_usb_8h__dep__incl.png differ diff --git a/annotated.html b/annotated.html index 56bdd666..2e403adb 100644 --- a/annotated.html +++ b/annotated.html @@ -64,7 +64,7 @@ $(function() {
Here are the classes, structs, unions and interfaces with brief descriptions:
- +
[detail level 12]
@@ -95,7 +95,9 @@ $(function() { - + + + diff --git a/class_h_i_d_composite-members.html b/class_h_i_d_composite-members.html index 07edf329..fb723196 100644 --- a/class_h_i_d_composite-members.html +++ b/class_h_i_d_composite-members.html @@ -67,15 +67,23 @@ $(function() {

This is the complete list of members for HIDComposite, including all inherited members.

 CACM
 CACM_FUNC_DESCR
 CAddressPool
 CHexDumper
 CHID_CLASS_DESCRIPTOR_LEN_AND_TYPE
 CHIDBoot
 CHIDComposite
 CHIDComposite
 CHidItemPrefix
 CHIDReportParser
 CHIDUniversal
- + + + + + + + - + + + @@ -86,18 +94,22 @@ $(function() { - - - - - - - + + + + + + + + + - - + + + + @@ -108,6 +120,7 @@ $(function() { +
bAddressUSBHIDprotected
bHasReportIdHIDCompositeprotected
bConfNumHIDCompositeprotected
bHasReportIdHIDCompositeprotected
bNumEPHIDCompositeprotected
bNumIfaceHIDCompositeprotected
bPollEnableHIDCompositeprotected
ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed)USBDeviceConfiginlinevirtual
constBuffLenHIDCompositeprotectedstatic
descrInfoHIDCompositeprotected
DEVCLASSOK(uint8_t klass)USBDeviceConfiginlinevirtual
DEVSUBCLASSOK(uint8_t subklass)USBDeviceConfiginlinevirtual
EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)HIDCompositevirtual
epInfoHIDCompositeprotected
epInterruptInIndexUSBHIDprotectedstatic
epInterruptOutIndexUSBHIDprotectedstatic
GetAddress()HIDCompositeinlinevirtual
FindInterface(uint8_t iface, uint8_t alt, uint8_t proto)HIDCompositeprotected
GetAddress()HIDCompositeinlinevirtual
GetHidClassDescrLen(uint8_t type, uint8_t num)HIDCompositeprotected
GetHidDescr(uint8_t ep, uint16_t nbytes, uint8_t *dataptr)USBHID
GetIdle(uint8_t iface, uint8_t reportID, uint8_t *dataptr)USBHID
GetProtocol(uint8_t iface, uint8_t *dataptr)USBHID
HIDComposite(USB *p)HIDComposite
hidInterfacesHIDCompositeprotected
Init(uint8_t parent, uint8_t port, bool lowspeed)HIDCompositevirtual
isReady()HIDCompositeinlinevirtual
maxEpPerInterfaceUSBHIDprotectedstatic
maxHidInterfacesUSBHIDprotectedstatic
OnInitSuccessful()HIDCompositeinlineprotectedvirtual
ParseHIDData(USBHID *hid, uint8_t ep, bool is_rpt_id, uint8_t len, uint8_t *buf)HIDCompositeinlineprotectedvirtual
PIDHIDCompositeprotected
Poll()HIDCompositevirtual
Initialize()HIDCompositeprotected
isReady()HIDCompositeinlinevirtual
maxEpPerInterfaceUSBHIDprotectedstatic
maxHidInterfacesUSBHIDprotectedstatic
OnInitSuccessful()HIDCompositeinlineprotectedvirtual
ParseHIDData(USBHID *hid, uint8_t ep, bool is_rpt_id, uint8_t len, uint8_t *buf)HIDCompositeinlineprotectedvirtual
PIDHIDCompositeprotected
Poll()HIDCompositevirtual
pollIntervalHIDCompositeprotected
PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)USBHIDprotected
PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)USBHIDprotected
pUsbUSBHIDprotected
Release()HIDCompositevirtual
ResetHubPort(uint8_t port)USBDeviceConfiginlinevirtual
qNextPollTimeHIDCompositeprotected
Release()HIDCompositevirtual
ResetHubPort(uint8_t port)USBDeviceConfiginlinevirtual
rptParsersHIDCompositeprotected
SelectInterface(uint8_t iface, uint8_t proto)=0HIDCompositepure virtual
SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration)USBHID
SetProtocol(uint8_t iface, uint8_t protocol)USBHID
USBHID(USB *pusb)USBHIDinline
VIDHIDCompositeprotected
VIDPIDOK(uint16_t vid, uint16_t pid)USBDeviceConfiginlinevirtual
ZeroMemory(uint8_t len, uint8_t *buf)HIDCompositeprotected
HIDComposite Class Referenceabstract
@@ -76,9 +77,12 @@ Inheritance diagram for HIDComposite:
Inheritance graph
+ + +
[legend]
@@ -86,15 +90,26 @@ Collaboration diagram for HIDComposite:
Collaboration graph
- - - - - - + + + + + + + + + +
[legend]
+ + + + + +

+Classes

struct  HIDInterface
 
struct  ReportParser
 
@@ -152,6 +167,14 @@ Public Member Functions

Public Member Functions

 HIDComposite (USB *p)
+ + + + + + + + @@ -166,9 +189,25 @@ Protected Member Functions

Protected Member Functions

uint16_t GetHidClassDescrLen (uint8_t type, uint8_t num)
 
void Initialize ()
 
HIDInterfaceFindInterface (uint8_t iface, uint8_t alt, uint8_t proto)
 
void ZeroMemory (uint8_t len, uint8_t *buf)
 
HIDReportParserGetReportParser (uint8_t id)
 
virtual uint8_t OnInitSuccessful ()
+ + + + + + + + + + + + + + + + - + @@ -182,8 +221,10 @@ Protected Attributes

Protected Attributes

struct HIDComposite::ReportParser rptParsers [MAX_REPORT_PARSERS]
 
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo [HID_MAX_HID_CLASS_DESCRIPTORS]
 
uint8_t bConfNum
 
uint8_t bNumIface
 
uint8_t bNumEP
 
uint32_t qNextPollTime
 
uint8_t pollInterval
 
bool bPollEnable
 
EpInfo epInfo [totalEndpoints]
 
HIDInterface hidInterfaces [maxHidInterfaces]
HIDInterface hidInterfaces [maxHidInterfaces]
 
bool bHasReportId
 
uint8_t bAddress
 
- + + + @@ -221,6 +262,153 @@ Additional Inherited Members

Member Function Documentation

+ +

◆ GetHidClassDescrLen()

+ +
+
+

-Additional Inherited Members

+Static Protected Attributes

static const uint16_t constBuffLen = 64
 
- Static Protected Attributes inherited from USBHID
static const uint8_t epInterruptInIndex = 1
 
+ + + + +
+ + + + + + + + + + + + + + + + + + +
uint16_t HIDComposite::GetHidClassDescrLen (uint8_t type,
uint8_t num 
)
+
+protected
+
+ +

Definition at line 32 of file hidcomposite.cpp.

+ +
+ + +

◆ Initialize()

+ +
+
+ + + + + +
+ + + + + + + +
void HIDComposite::Initialize ()
+
+protected
+
+ +

Definition at line 43 of file hidcomposite.cpp.

+ +
+
+ +

◆ FindInterface()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
HIDComposite::HIDInterface * HIDComposite::FindInterface (uint8_t iface,
uint8_t alt,
uint8_t proto 
)
+
+protected
+
+ +

Definition at line 289 of file hidcomposite.cpp.

+ +
+
+ +

◆ ZeroMemory()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void HIDComposite::ZeroMemory (uint8_t len,
uint8_t * buf 
)
+
+protected
+
+ +

Definition at line 364 of file hidcomposite.cpp.

+ +
+

◆ GetReportParser()

@@ -274,7 +462,9 @@ Additional Inherited Members
-

Definition at line 71 of file hidcomposite.h.

+

Reimplemented in PSBuzz, and PS4USB.

+ +

Definition at line 76 of file hidcomposite.h.

@@ -330,7 +520,7 @@ Additional Inherited Members
-

Definition at line 75 of file hidcomposite.h.

+

Definition at line 80 of file hidcomposite.h.

@@ -474,6 +664,8 @@ Additional Inherited Members

Reimplemented from USBDeviceConfig.

+

Reimplemented in HIDUniversal.

+

Definition at line 369 of file hidcomposite.cpp.

@@ -503,7 +695,7 @@ Additional Inherited Members

Reimplemented from USBDeviceConfig.

-

Definition at line 90 of file hidcomposite.h.

+

Definition at line 95 of file hidcomposite.h.

@@ -530,7 +722,7 @@ Additional Inherited Members
-

Definition at line 94 of file hidcomposite.h.

+

Definition at line 99 of file hidcomposite.h.

@@ -588,6 +780,8 @@ Additional Inherited Members

Reimplemented from UsbConfigXtracter.

+

Reimplemented in HIDUniversal.

+

Definition at line 297 of file hidcomposite.cpp.

@@ -659,6 +853,220 @@ Additional Inherited Members

Member Data Documentation

+ +

◆ rptParsers

+ +
+
+ + + + + +
+ + + + +
struct HIDComposite::ReportParser HIDComposite::rptParsers[MAX_REPORT_PARSERS]
+
+protected
+
+ +
+
+ +

◆ descrInfo

+ +
+
+ + + + + +
+ + + + +
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE HIDComposite::descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS]
+
+protected
+
+ +

Definition at line 34 of file hidcomposite.h.

+ +
+
+ +

◆ bConfNum

+ +
+
+ + + + + +
+ + + + +
uint8_t HIDComposite::bConfNum
+
+protected
+
+ +

Definition at line 48 of file hidcomposite.h.

+ +
+
+ +

◆ bNumIface

+ +
+
+ + + + + +
+ + + + +
uint8_t HIDComposite::bNumIface
+
+protected
+
+ +

Definition at line 49 of file hidcomposite.h.

+ +
+
+ +

◆ bNumEP

+ +
+
+ + + + + +
+ + + + +
uint8_t HIDComposite::bNumEP
+
+protected
+
+ +

Definition at line 50 of file hidcomposite.h.

+ +
+
+ +

◆ qNextPollTime

+ +
+
+ + + + + +
+ + + + +
uint32_t HIDComposite::qNextPollTime
+
+protected
+
+ +

Definition at line 51 of file hidcomposite.h.

+ +
+
+ +

◆ pollInterval

+ +
+
+ + + + + +
+ + + + +
uint8_t HIDComposite::pollInterval
+
+protected
+
+ +

Definition at line 52 of file hidcomposite.h.

+ +
+
+ +

◆ bPollEnable

+ +
+
+ + + + + +
+ + + + +
bool HIDComposite::bPollEnable
+
+protected
+
+ +

Definition at line 53 of file hidcomposite.h.

+ +
+
+ +

◆ constBuffLen

+ +
+
+ + + + + +
+ + + + +
const uint16_t HIDComposite::constBuffLen = 64
+
+staticprotected
+
+ +

Definition at line 55 of file hidcomposite.h.

+ +
+

◆ epInfo

@@ -679,7 +1087,7 @@ Additional Inherited Members
-

Definition at line 61 of file hidcomposite.h.

+

Definition at line 63 of file hidcomposite.h.

@@ -693,7 +1101,7 @@ Additional Inherited Members - +
HIDInterface HIDComposite::hidInterfaces[maxHidInterfaces]HIDInterface HIDComposite::hidInterfaces[maxHidInterfaces]
@@ -703,7 +1111,7 @@ Additional Inherited Members
-

Definition at line 62 of file hidcomposite.h.

+

Definition at line 64 of file hidcomposite.h.

@@ -727,7 +1135,7 @@ Additional Inherited Members
-

Definition at line 64 of file hidcomposite.h.

+

Definition at line 69 of file hidcomposite.h.

@@ -751,7 +1159,7 @@ Additional Inherited Members
-

Definition at line 66 of file hidcomposite.h.

+

Definition at line 71 of file hidcomposite.h.

@@ -775,7 +1183,7 @@ Additional Inherited Members
-

Definition at line 66 of file hidcomposite.h.

+

Definition at line 71 of file hidcomposite.h.

diff --git a/class_h_i_d_composite__coll__graph.map b/class_h_i_d_composite__coll__graph.map index d7ae0f68..ed634bfd 100644 --- a/class_h_i_d_composite__coll__graph.map +++ b/class_h_i_d_composite__coll__graph.map @@ -1,8 +1,12 @@ - - - - - - + + + + + + + + + + diff --git a/class_h_i_d_composite__coll__graph.md5 b/class_h_i_d_composite__coll__graph.md5 index 8c822c0b..e821c52e 100644 --- a/class_h_i_d_composite__coll__graph.md5 +++ b/class_h_i_d_composite__coll__graph.md5 @@ -1 +1 @@ -53a6c18af1475d71fd895b0881f48e79 \ No newline at end of file +3f9346dcd1abe9337a6e311a46ba14f4 \ No newline at end of file diff --git a/class_h_i_d_composite__coll__graph.png b/class_h_i_d_composite__coll__graph.png index 76bf03c9..0e13d5c5 100644 Binary files a/class_h_i_d_composite__coll__graph.png and b/class_h_i_d_composite__coll__graph.png differ diff --git a/class_h_i_d_composite__inherit__graph.map b/class_h_i_d_composite__inherit__graph.map index 408d5f41..4959edcc 100644 --- a/class_h_i_d_composite__inherit__graph.map +++ b/class_h_i_d_composite__inherit__graph.map @@ -1,5 +1,8 @@ + + + diff --git a/class_h_i_d_composite__inherit__graph.md5 b/class_h_i_d_composite__inherit__graph.md5 index 8e8d4518..995c3b05 100644 --- a/class_h_i_d_composite__inherit__graph.md5 +++ b/class_h_i_d_composite__inherit__graph.md5 @@ -1 +1 @@ -5365f14a032a8fd6dcc87df5954edbd5 \ No newline at end of file +55a554165c31a4332eebfdfa1938f9a4 \ No newline at end of file diff --git a/class_h_i_d_composite__inherit__graph.png b/class_h_i_d_composite__inherit__graph.png index f596e486..a67d180a 100644 Binary files a/class_h_i_d_composite__inherit__graph.png and b/class_h_i_d_composite__inherit__graph.png differ diff --git a/class_h_i_d_universal-members.html b/class_h_i_d_universal-members.html index 9f8fb2ba..b1d3ed1a 100644 --- a/class_h_i_d_universal-members.html +++ b/class_h_i_d_universal-members.html @@ -67,46 +67,60 @@ $(function() {

This is the complete list of members for HIDUniversal, including all inherited members.

- + + + + + + + - - + + - + + + - + - - - - + + + + + + - + - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + + +
bAddressUSBHIDprotected
bHasReportIdHIDUniversalprotected
bConfNumHIDCompositeprotected
bHasReportIdHIDCompositeprotected
bNumEPHIDCompositeprotected
bNumIfaceHIDCompositeprotected
bPollEnableHIDCompositeprotected
ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed)USBDeviceConfiginlinevirtual
constBuffLenHIDCompositeprotectedstatic
descrInfoHIDCompositeprotected
DEVCLASSOK(uint8_t klass)USBDeviceConfiginlinevirtual
DEVSUBCLASSOK(uint8_t subklass)USBDeviceConfiginlinevirtual
EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)HIDUniversalvirtual
epInfoHIDUniversalprotected
EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) overrideHIDUniversalinlinevirtual
epInfoHIDCompositeprotected
epInterruptInIndexUSBHIDprotectedstatic
epInterruptOutIndexUSBHIDprotectedstatic
GetAddress()HIDUniversalinlinevirtual
FindInterface(uint8_t iface, uint8_t alt, uint8_t proto)HIDCompositeprotected
GetAddress()HIDCompositeinlinevirtual
GetHidClassDescrLen(uint8_t type, uint8_t num)HIDCompositeprotected
GetHidDescr(uint8_t ep, uint16_t nbytes, uint8_t *dataptr)USBHID
GetIdle(uint8_t iface, uint8_t reportID, uint8_t *dataptr)USBHID
GetProtocol(uint8_t iface, uint8_t *dataptr)USBHID
GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t *dataptr)USBHID
GetReportDescr(uint16_t wIndex, USBReadParser *parser=NULL)USBHID
GetReportParser(uint8_t id)HIDUniversalprotectedvirtual
GetReportParser(uint8_t id)HIDCompositeprotectedvirtual
GetUsb()USBHIDinline
hidInterfacesHIDUniversalprotected
HIDUniversal(USB *p)HIDUniversal
Init(uint8_t parent, uint8_t port, bool lowspeed)HIDUniversalvirtual
isReady()HIDUniversalinlinevirtual
HIDComposite(USB *p)HIDComposite
hidInterfacesHIDCompositeprotected
HIDUniversal(USB *p)HIDUniversalinline
Init(uint8_t parent, uint8_t port, bool lowspeed)HIDCompositevirtual
Initialize()HIDCompositeprotected
isReady()HIDCompositeinlinevirtual
maxEpPerInterfaceUSBHIDprotectedstatic
maxHidInterfacesUSBHIDprotectedstatic
OnInitSuccessful()HIDUniversalinlineprotectedvirtual
OnInitSuccessful()HIDCompositeinlineprotectedvirtual
ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)HIDUniversalinlineprotectedvirtual
PIDHIDUniversalprotected
Poll()HIDUniversalvirtual
PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)USBHIDprotected
PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)USBHIDprotected
pUsbUSBHIDprotected
Release()HIDUniversalvirtual
PIDHIDCompositeprotected
Poll() overrideHIDUniversalvirtual
pollIntervalHIDCompositeprotected
PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)USBHIDprotected
PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)USBHIDprotected
pUsbUSBHIDprotected
qNextPollTimeHIDCompositeprotected
Release()HIDCompositevirtual
ResetHubPort(uint8_t port)USBDeviceConfiginlinevirtual
SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration)USBHID
SetProtocol(uint8_t iface, uint8_t protocol)USBHID
SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t *dataptr)USBHID
SetReportParser(uint8_t id, HIDReportParser *prs)HIDUniversalvirtual
SndRpt(uint16_t nbytes, uint8_t *dataptr)HIDUniversal
totalEndpointsUSBHIDprotectedstatic
USBHID(USB *pusb)USBHIDinline
VIDHIDUniversalprotected
VIDPIDOK(uint16_t vid, uint16_t pid)USBDeviceConfiginlinevirtual
rptParsersHIDCompositeprotected
SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration)USBHID
SetProtocol(uint8_t iface, uint8_t protocol)USBHID
SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t *dataptr)USBHID
SetReportParser(uint8_t id, HIDReportParser *prs)HIDCompositevirtual
SndRpt(uint16_t nbytes, uint8_t *dataptr)HIDComposite
totalEndpointsUSBHIDprotectedstatic
USBHID(USB *pusb)USBHIDinline
VIDHIDCompositeprotected
VIDPIDOK(uint16_t vid, uint16_t pid)USBDeviceConfiginlinevirtual
ZeroMemory(uint8_t len, uint8_t *buf)HIDCompositeprotected