embkernel
 All Classes Functions Variables Typedefs Groups Pages
UsbDevice.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "UsbDevice.hpp"
7 #include "LibEndian.hpp"
8 #include "UsbMacros.hpp"
9 
10 RtosTask* UsbDevice::sTask;
11 UsbHw* UsbDevice::sUsbHw;
12 RtosSemaphore UsbDevice::sSemaEvent(255, 0);
13 RtosSemaphore UsbDevice::sSemaLock(1, 1);
14 uint8_t UsbDevice::sAddress;
15 UsbDevice::STATUS UsbDevice::sStatus;
16 size_t UsbDevice::sEp0DataInLen;
17 const uint8_t* UsbDevice::sEp0DataInBuffer;
18 bool UsbDevice::sIsReady = false;
19 UsbDefs::PKT UsbDevice::sPkt;
20 UsbInCallback* UsbDevice::sInCallback[USB_CFG_MAX_EPN] = { 0 };
21 UsbOutCallback* UsbDevice::sOutCallback[USB_CFG_MAX_EPN] = { 0 };
22 
23 void UsbDevice::init(Rtos::PRIORITY priority, size_t stackSize, UsbHw* usbHw) {
24  sTask = new RtosTask(priority, "USB", stackSize, run);
25  sUsbHw = usbHw;
26  sAddress = 0;
27 }
28 
29 bool UsbDevice::isReady() {
30  return sIsReady;
31 }
32 
33 void UsbDevice::notifyDataInReadyForEp(uint8_t ep) {
34  sSemaLock.take(Rtos::TICK_INFINITE);
35  int len = sUsbHw->getEpInFree(ep);
36  if (len > 0) {
37  if (sInCallback[ep]) {
38  sInCallback[ep]->onDataInFree(ep, len);
39  }
40  }
41  sSemaLock.give(Rtos::TICK_INFINITE);
42 }
43 
44 int UsbDevice::writeBuffer(uint8_t ep, const uint8_t* buffer, int len) {
45  return sUsbHw->writeEp(ep, buffer, len);
46 }
47 
48 void UsbDevice::registerInCallback(uint8_t ep, UsbInCallback* cb) {
49  USB_ASSERT(ep < USB_CFG_MAX_EPN);
50  sInCallback[ep] = cb;
51 }
52 
53 void UsbDevice::registerOutCallback(uint8_t ep, UsbOutCallback* cb) {
54  USB_ASSERT(ep < USB_CFG_MAX_EPN);
55  sOutCallback[ep] = cb;
56 }
57 
58 void UsbDevice::run(RtosTask*) {
59  sUsbHw->init();
60  sIsReady = true;
61  while (true) {
62  if (sSemaEvent.take(Rtos::TICK_INFINITE)) {
63  sSemaLock.take(Rtos::TICK_INFINITE);
64  sUsbHw->processEvents();
65  sSemaLock.give(Rtos::TICK_INFINITE);
66  }
67  }
68 }
69 
70 void UsbDevice::processEp0Setup(UsbDefs::PKT* pkt) {
71  UsbDefs::USB_SETUP_PACKET* setup = (UsbDefs::USB_SETUP_PACKET*) pkt->data.bytes;
72  setup->wValue = LibEndian::leToHw(setup->wValue);
73  setup->wIndex = LibEndian::leToHw(setup->wIndex);
74  setup->wLength = LibEndian::leToHw(setup->wLength);
75 
76 //See http://www.beyondlogic.org/usbnutshell/usb6.shtml
77  switch (setup->bmRequestType.bits.type) {
78  case UsbDefs::TYPE_STANDARD:
79  switch (setup->bmRequestType.bits.recipient) {
80  case UsbDefs::RECIPIENT_DEVICE:
81  switch (setup->bRequest) {
82  case UsbDefs::REQ_CODE_GET_STATUS:
83  sUsbHw->writeEp(0, (uint8_t*) &sStatus.value, sizeof(sStatus.value));
84  break;
85  case UsbDefs::REQ_CODE_CLEAR_FEATURE:
86  Rtos::nop();
87  break;
88  case UsbDefs::REQ_CODE_SET_FEATURE:
89  Rtos::nop();
90  break;
91  case UsbDefs::REQ_CODE_SET_ADDR:
92  sAddress = (setup->wValue & 0xFF) | 0x80;
93  sUsbHw->writeEp(0, 0, 0);
94  break;
95  case UsbDefs::REQ_CODE_GET_DESC:
96  reqGetDeviceDescriptor((UsbDefs::DESC_TYPE) (setup->wValue >> 8), (setup->wValue & 0xFF), setup->wIndex, setup->wLength);
97  break;
98  case UsbDefs::REQ_CODE_SET_DESC:
99  Rtos::nop();
100  break;
101  case UsbDefs::REQ_CODE_GET_CONFIG:
102  Rtos::nop();
103  break;
104  case UsbDefs::REQ_CODE_SET_CONFIG:
105  reqSetConfig(setup->wValue & 0xFF);
106  break;
107  default:
108  break;
109  }
110  break;
111  case UsbDefs::RECIPIENT_INTERFACE:
112  switch (setup->bRequest) {
113  case UsbDefs::REQ_CODE_GET_STATUS:
114  Rtos::nop();
115  break;
116  case UsbDefs::REQ_CODE_CLEAR_FEATURE:
117  Rtos::nop();
118  break;
119  case UsbDefs::REQ_CODE_SET_FEATURE:
120  Rtos::nop();
121  break;
122  case UsbDefs::REQ_CODE_GET_INTERFACE:
123  Rtos::nop();
124  break;
125  case UsbDefs::REQ_CODE_SET_INTERFACE:
126  Rtos::nop();
127  break;
128  default:
129  break;
130  }
131  break;
132  case UsbDefs::RECIPIENT_ENDPOINT:
133  switch (setup->bRequest) {
134  case UsbDefs::REQ_CODE_GET_STATUS:
135  Rtos::nop();
136  break;
137  case UsbDefs::REQ_CODE_CLEAR_FEATURE:
138  Rtos::nop();
139  break;
140  case UsbDefs::REQ_CODE_SET_FEATURE:
141  Rtos::nop();
142  break;
143  case UsbDefs::REQ_CODE_SYNCH_FRAME:
144  Rtos::nop();
145  break;
146  default:
147  break;
148  }
149  break;
150  }
151  case UsbDefs::TYPE_CLASS:
152  break;
153  case UsbDefs::TYPE_VENDOR:
154  break;
155 
156  }
157 }
158 
159 void UsbDevice::processEp0DataOut(UsbDefs::PKT* pkt) {
160 
161 }
162 
163 const uint8_t* UsbDevice::findInsideDescriptor(UsbDefs::DESC_TYPE descType, uint8_t index) {
164  const uint8_t* parser = sDescriptor;
165  uint8_t currentIndex = 0;
166 
167  while (true) {
168  if (*parser == 0) {
169  return 0;
170  }
171  if (parser[1] == descType) {
172  if (currentIndex == index) {
173  return parser;
174  }
175  currentIndex++;
176  }
177 
178  parser += *parser;
179  }
180 }
181 
182 bool UsbDevice::reqGetDeviceDescriptor(UsbDefs::DESC_TYPE descType, uint8_t index, uint16_t lang, uint16_t len) {
183  sEp0DataInBuffer = findInsideDescriptor(descType, index);
184  if (!sEp0DataInBuffer) {
185  return false;
186  }
187  switch (descType) {
188  case UsbDefs::DESC_TYPE_CONFIG: {
189  UsbDefs::USB_DESC_CONFIG* config = (UsbDefs::USB_DESC_CONFIG*) sEp0DataInBuffer;
190  if (len > config->wTotalLength) {
191  len = config->wTotalLength;
192  }
193  break;
194  }
195  case UsbDefs::DESC_TYPE_DEVICE:
196  case UsbDefs::DESC_TYPE_STRING:
197  case UsbDefs::DESC_TYPE_INTERFACE:
198  case UsbDefs::DESC_TYPE_ENDPOINT:
199  case UsbDefs::DESC_TYPE_DEVICE_QUALIFIER:
200  case UsbDefs::DESC_TYPE_OTHER_SPEED_CONF:
201  case UsbDefs::DESC_TYPE_INTERFACE_POWER:
202  if (len > sEp0DataInBuffer[0]) {
203  len = sEp0DataInBuffer[0];
204  }
205  break;
206  }
207  sEp0DataInLen = len;
208  len = sUsbHw->writeEp(0, sEp0DataInBuffer, sEp0DataInLen);
209  sEp0DataInLen -= len;
210  sEp0DataInBuffer += len;
211 
212  return true;
213 }
214 
215 bool UsbDevice::reqSetConfig(uint16_t index) {
216  const UsbDefs::USB_DESC_CONFIG* config = (const UsbDefs::USB_DESC_CONFIG*) findInsideDescriptor(UsbDefs::DESC_TYPE_CONFIG, index - 1);
217  if (!config) {
218  return false;
219  }
220  sUsbHw->epResetAll();
221  sStatus.value = 0;
222  if (config->bmAttributes & UsbDefs::DESC_CONFIG_ATTR_SELF_POWERED) {
223  sStatus.bits.selfPowered = 1;
224  }
225  if (config->bmAttributes & UsbDefs::DESC_CONFIG_ATTR_REMOTE_WAKEUP) {
226  sStatus.bits.remoteWakeup = 1;
227  }
228 
229  const uint8_t* parser = (const uint8_t*) config;
230  while (true) {
231  if (*parser == 0) {
232  break;
233  }
234  if (parser[1] == UsbDefs::DESC_TYPE_ENDPOINT) {
235  sUsbHw->epConfig((const UsbDefs::USB_DESC_EP*) parser);
236  }
237  parser += *parser;
238  }
239  sUsbHw->writeEp(0, 0, 0);
240  return true;
241 }
242 
243 void UsbDevice::onDataIn(uint8_t ep, uint16_t len) {
244  if (ep == 0) {
245  if (sAddress & 0x80) {
246  sAddress = sAddress & 0x7F;
247  sUsbHw->setAddress(sAddress);
248  }
249  if (sEp0DataInLen > 0) {
250  sEp0DataInLen -= sUsbHw->writeEp(0, sEp0DataInBuffer, sEp0DataInLen);
251  }
252  }
253  len = sUsbHw->getEpInFree(ep);
254  if (len > 0) {
255  if (sInCallback[ep]) {
256  sInCallback[ep]->onDataInFree(ep, len);
257  }
258  }
259 }
260 
261 void UsbDevice::onDataOut(uint8_t ep, bool isSetup, uint16_t len) {
262  USB_ASSERT(len <= UsbDefs::MAX_PACKET_SIZE)
263 
264  //USB_TYPES::PKT sPkt;
265  sPkt.header.epn = ep;
266  sPkt.header.len = len;
267  sPkt.header.isSetup = isSetup;
268  sUsbHw->readEp(ep, sPkt.data.bytes, len);
269  if (ep == 0) {
270  if (isSetup) {
271  processEp0Setup(&sPkt);
272  }
273  else {
274  processEp0DataOut(&sPkt);
275  }
276  }
277  if (sOutCallback[ep]) {
278  sOutCallback[ep]->onDataOut(&sPkt);
279  }
280 }
281 
282 void UsbDevice::onReset() {
283  sStatus.value = 0;
284 }
285 
286 bool UsbDevice::onEventInterrupt() {
287  return sSemaEvent.giveFromInt();
288 }