Numworks Epsilon  1.4.1
Graphing Calculator Operating System
device.cpp
Go to the documentation of this file.
1 #include "device.h"
2 #include "../regs/regs.h"
3 
4 namespace Ion {
5 namespace USB {
6 namespace Device {
7 
8 static inline uint16_t min(uint16_t x, uint16_t y) { return (x<y ? x : y); }
9 
10 void Device::poll() {
11  // Read the interrupts
12  class OTG::GINTSTS intsts(OTG.GINTSTS()->get());
13 
14  /* SETUP or OUT transaction
15  * If the Rx FIFO is not empty, there is a SETUP or OUT transaction.
16  * The interrupt is done AFTER THE HANSDHAKE of the transaction. */
17  if (intsts.getRXFLVL()) {
18  class OTG::GRXSTSP grxstsp(OTG.GRXSTSP()->get());
19 
20  // Store the packet status
21  OTG::GRXSTSP::PKTSTS pktsts = grxstsp.getPKTSTS();
22 
23  // We only use endpoint 0
24  assert(grxstsp.getEPNUM() == 0);
25 
27  // There is no data associated with this interrupt.
28  return;
29  }
30 
32  /* We did not enable the GONAKEFFM (Global OUT NAK effective mask) bit in
33  * GINTSTS, so we should never get this interrupt. */
34 
36 
37  TransactionType type = (pktsts == OTG::GRXSTSP::PKTSTS::OutReceived) ? TransactionType::Out : TransactionType::Setup;
38 
39  if (type == TransactionType::Setup && OTG.DIEPTSIZ0()->getPKTCNT()) {
40  // SETUP received but there is a packet in the Tx FIFO. Flush it.
42  }
43 
44  // Save the received packet byte count
45  m_ep0.setReceivedPacketSize(grxstsp.getBCNT());
46 
47  if (type == TransactionType::Setup) {
49  } else {
50  assert(type == TransactionType::Out);
52  }
53 
55  }
56 
57  /* IN transactions.
58  * The interrupt is done AFTER THE HANSDHAKE of the transaction. */
59  if (OTG.DIEPINT(0)->getXFRC()) { // We only check endpoint 0.
61  // Clear the Transfer Completed Interrupt
62  OTG.DIEPINT(0)->setXFRC(true);
63  }
64 
65  // Handle USB RESET. ENUMDNE = **SPEED** Enumeration Done
66  if (intsts.getENUMDNE()) {
67  // Clear the ENUMDNE bit
68  OTG.GINTSTS()->setENUMDNE(true);
69  /* After a USB reset, the host talks to the device by sending messages to
70  * address 0; */
71  setAddress(0);
72  // Flush the FIFOs
73  m_ep0.reset();
74  m_ep0.setup();
75  /* In setup(), we should set the MPSIZ field in OTG_DIEPCTL0 to the maximum
76  * packet size depending on the enumeration speed (found in OTG_DSTS). We
77  * should always get FullSpeed, so we set the packet size accordingly. */
78  }
79 }
80 
81 bool Device::isSoftDisconnected() const {
82  return OTG.DCTL()->getSDIS();
83 }
84 
85 void Device::detach() {
86  // Get in soft-disconnected state
87  OTG.DCTL()->setSDIS(true);
88 }
89 
90 bool Device::processSetupInRequest(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t transferBufferMaxLength) {
91  // Device only handles standard requests.
93  return false;
94  }
95  switch (request->bRequest()) {
96  case (int) Request::GetStatus:
97  return getStatus(transferBuffer, transferBufferLength, transferBufferMaxLength);
98  case (int) Request::SetAddress:
99  // Make sure the request is adress is valid.
100  assert(request->wValue() < 128);
101  /* According to the reference manual, the address should be set after the
102  * Status stage of the current transaction, but this is not true.
103  * It should be set here, after the Data stage. */
104  setAddress(request->wValue());
105  *transferBufferLength = 0;
106  return true;
107  case (int) Request::GetDescriptor:
108  return getDescriptor(request, transferBuffer, transferBufferLength, transferBufferMaxLength);
109  case (int) Request::SetConfiguration:
110  *transferBufferLength = 0;
111  return setConfiguration(request);
112  case (int) Request::GetConfiguration:
113  return getConfiguration(transferBuffer, transferBufferLength);
114  }
115  return false;
116 }
117 
118 bool Device::getStatus(uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t transferBufferMaxLength) {
119  *transferBufferLength = min(2, transferBufferMaxLength);
120  for (int i = 0; i<*transferBufferLength; i++) {
121  transferBuffer[i] = 0; // No remote wakeup, not self-powered.
122  }
123  return true;
124 }
125 
126 void Device::setAddress(uint8_t address) {
127  OTG.DCFG()->setDAD(address);
128 }
129 
130 bool Device::getDescriptor(SetupPacket * request, uint8_t * transferBuffer, uint16_t * transferBufferLength, uint16_t transferBufferMaxLength) {
131  Descriptor * wantedDescriptor = descriptor(request->descriptorType(), request->descriptorIndex());
132  if (wantedDescriptor == nullptr) {
133  return false;
134  }
135  *transferBufferLength = wantedDescriptor->copy(transferBuffer, transferBufferMaxLength);
136  return true;
137 }
138 
139 bool Device::getConfiguration(uint8_t * transferBuffer, uint16_t * transferBufferLength) {
140  *transferBufferLength = 1;
141  transferBuffer[0] = getActiveConfiguration();
142  return true;
143 }
144 
145 bool Device::setConfiguration(SetupPacket * request) {
146  // We support one configuration only
147  setActiveConfiguration(request->wValue());
148  /* There is one configuration only, we no need to set it again, just reset the
149  * endpoint. */
150  m_ep0.reset();
151  return true;
152 }
153 
154 }
155 }
156 }
#define assert(e)
Definition: assert.h:9
unsigned short uint16_t
Definition: stdint.h:5
virtual void setActiveConfiguration(uint8_t configurationIndex)=0
unsigned char uint8_t
Definition: stdint.h:4
Definition: otg.h:94
T get() volatile
Definition: register.h:18
uint16_t copy(void *target, size_t maxSize) const
Definition: streamable.cpp:7
Definition: otg.h:85
virtual uint8_t getActiveConfiguration()=0
constexpr volatile DIEPINT * DIEPINT(int i) const
Definition: otg.h:184
Definition: app.cpp:5
virtual Descriptor * descriptor(uint8_t type, uint8_t index)=0
void setReceivedPacketSize(uint16_t size)
Definition: endpoint0.h:52
PKTSTS getPKTSTS() volatile
Definition: otg.h:65
RequestType requestType() const
Definition: otg.h:6
Definition: backlight.h:6