source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/USBCore.cpp@ 259

Last change on this file since 259 was 259, checked in by ertl-honda, 8 years ago

1.7.11に対応.

File size: 18.5 KB
RevLine 
[136]1/*
[224]2 Copyright (c) 2015 Arduino LLC. All right reserved.
[136]3
[224]4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
[136]8
[224]9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 See the GNU Lesser General Public License for more details.
[136]13
[224]14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17*/
[136]18/*
[224]19**Modified 04/04/2016 by Arduino.org development team
[136]20*/
21
[224]22#include <Arduino.h>
[136]23
[224]24#include "SAMD21_USBDevice.h"
25#include "USB_host.h"
[136]26
[224]27#include <stdlib.h>
28#include <stdio.h>
29#include <stdint.h>
30#include <limits.h>
[136]31
[224]32USBDevice_SAMD21G18x usbd;
33
[136]34static char isRemoteWakeUpEnabled = 0;
35static char isEndpointHalt = 0;
36
[224]37extern void (*gpf_isr)(void);
[136]38
[224]39
[136]40const uint16_t STRING_LANGUAGE[2] = {
41 (3<<8) | (2+2),
42 0x0409 // English
43};
44
[224]45#define USB_PID_ZERO_PRO 0x804d
[259]46
[136]47#ifndef USB_PRODUCT
48// Use a hardcoded product name if none is provided
49#if USB_PID == USB_PID_ZERO_PRO
50 #define USB_PRODUCT "Arduino Zero Pro"
51#else
52 #define USB_PRODUCT "USB IO Board"
53#endif
54#endif
55
56const uint8_t STRING_PRODUCT[] = USB_PRODUCT;
57
58#if USB_VID == 0x2a03
59# if defined(USB_MANUFACTURER)
60# undef USB_MANUFACTURER
61# endif
62# define USB_MANUFACTURER "Arduino Srl"
63#elif !defined(USB_MANUFACTURER)
64// Fall through to unknown if no manufacturer name was provided in a macro
65# define USB_MANUFACTURER "Unknown"
66#endif
67
68const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER;
69
70
71#if (defined CDC_ENABLED) && defined(HID_ENABLED)
72const DeviceDescriptor USB_DeviceDescriptor =
73 D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
74#elif defined(CDC_ENABLED) // CDC only
75const DeviceDescriptor USB_DeviceDescriptor =
76 D_DEVICE(0x02,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
77#else // HID only
78const DeviceDescriptor USB_DeviceDescriptor =
79 D_DEVICE(0,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
80#endif
81
[224]82
[136]83//==================================================================
84
85volatile uint32_t _usbConfiguration = 0;
86volatile uint32_t _usbSetInterface = 0;
87
[224]88static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0")))
89uint8_t udd_ep_out_cache_buffer[7][64];
90
91static __attribute__((__aligned__(4))) //__attribute__((__section__(".bss_hram0")))
92uint8_t udd_ep_in_cache_buffer[7][64];
93
[136]94//==================================================================
95
[224]96bool _dry_run = false;
97bool _pack_message = false;
98uint16_t _pack_size = 0;
99uint8_t _pack_buffer[256];
[136]100
[224]101
102void packMessages(bool val)
[136]103{
[224]104 if (val) {
105 _pack_message = true;
106 _pack_size = 0;
107 } else {
108 _pack_message = false;
109 USBD_SendControl(_pack_buffer, _pack_size);
110 }
[136]111}
112
[224]113// Blocking Send of data to an endpoint
114uint32_t USBD_Send(uint32_t ep, const void *data, uint32_t len)
[136]115{
[224]116 uint32_t length = 0;
117
118 if (!_usbConfiguration)
[136]119 return -1;
[224]120 if (len > 16384)
121 return -1;
[136]122
[224]123 PORT->Group[0].OUTCLR.reg =0x08000000 ; //TxLED on
124 // Flash area
125 while (len != 0)
[136]126 {
[224]127 if (len >= 64) {
128 length = 64;
129 } else {
130 length = len;
131 }
132
133 /* memcopy could be safer in multi threaded environment */
134 memcpy(&udd_ep_in_cache_buffer[ep], data, length);
135
136 usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
137
138 usbd.epBank1SetByteCount(ep, length);
139
140 // Clear the transfer complete flag
141 usbd.epBank1AckTransferComplete(ep);
142
143 // RAM buffer is full, we can send data (IN)
144 usbd.epBank1SetReady(ep);
145
146 // Wait for transfer to complete
147 while (!usbd.epBank1IsTransferComplete(ep)) {
148 ; // need fire exit.
149 }
150 len -= length;
151 data = (char *)data + length;
[136]152 }
153 return len;
154}
155
[224]156uint32_t USBD_armSend(uint32_t ep, const void* data, uint32_t len)
[136]157{
[224]158 memcpy(&udd_ep_in_cache_buffer[ep], data, len);
[136]159
[224]160 // Get endpoint configuration from setting register
161 usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
162 usbd.epBank1SetMultiPacketSize(ep, 0);
163 usbd.epBank1SetByteCount(ep, len);
[136]164
[224]165 return len;
[136]166}
167
[224]168uint32_t USBD_SendControl(const void* _data, uint32_t len)
[136]169{
[224]170 const uint8_t *data = reinterpret_cast<const uint8_t *>(_data);
[136]171 uint32_t length = len;
172 uint32_t sent = 0;
173 uint32_t pos = 0;
174
[224]175 if (_dry_run == true)
176 return length;
[136]177
[224]178 if (_pack_message == true) {
179 memcpy(&_pack_buffer[_pack_size], data, len);
180 _pack_size += len;
181 return length;
182 }
[136]183
[224]184 while (len > 0)
185 {
186 sent = USBD_armSend(EP0, data + pos, len);
187 pos += sent;
188 len -= sent;
189 }
190
[136]191 return length;
192}
193
[224]194bool USBD_SendStringDescriptor(const uint8_t *string, uint8_t maxlen)
[136]195{
[224]196 if (maxlen < 2)
197 return false;
198
199 uint16_t buff[maxlen/2];
[136]200 int l = 1;
201
[224]202 maxlen -= 2;
203 while (*string && maxlen>0)
[136]204 {
205 buff[l++] = (uint8_t)(*string++);
[224]206 maxlen -= 2;
[136]207 }
208 buff[0] = (3<<8) | (l*2);
209
[224]210 return USBD_SendControl((uint8_t*)buff, l*2);
[136]211}
212
[224]213uint8_t USBD_SendInterfaces(uint32_t* total)
[136]214{
[224]215 uint8_t interfaces = 0;
[136]216
[224]217#if defined(CDC_ENABLED)
218 total[0] += CDC_GetInterface(&interfaces);
219#endif
220
221 return interfaces;
[136]222}
223
[224]224// Construct a dynamic configuration descriptor
225// This really needs dynamic endpoint allocation etc
226uint32_t USBD_SendConfiguration(uint32_t maxlen)
[136]227{
[224]228 uint32_t total = 0;
229 // Count and measure interfaces
230 _dry_run = true;
231 uint8_t interfaces = USBD_SendInterfaces(&total);
[136]232
[224]233 _Pragma("pack(1)")
234 ConfigDescriptor config = D_CONFIG((uint16_t)(total + sizeof(ConfigDescriptor)), interfaces);
235 _Pragma("pack()")
[136]236
[224]237 // Now send them
238 _dry_run = false;
[136]239
[224]240 if (maxlen == sizeof(ConfigDescriptor)) {
241 USBD_SendControl(&config, sizeof(ConfigDescriptor));
[136]242 return true;
243 }
244
[224]245 total = 0;
246
247 packMessages(true);
248 USBD_SendControl(&config, sizeof(ConfigDescriptor));
249 USBD_SendInterfaces(&total);
250 packMessages(false);
251
252 return true;
[136]253}
254
[224]255bool USBD_SendDescriptor(Setup &setup)
[136]256{
[224]257 uint8_t t = setup.wValueH;
258 uint8_t desc_length = 0;
259 bool _cdcComposite;
260 int ret;
261 const uint8_t *desc_addr = 0;
[136]262
[224]263 if (t == USB_CONFIGURATION_DESCRIPTOR_TYPE)
[136]264 {
[224]265 return USBD_SendConfiguration(setup.wLength);
[136]266 }
267
[224]268 if (t == USB_DEVICE_DESCRIPTOR_TYPE)
[136]269 {
[224]270 if (setup.wLength == 8)
271 _cdcComposite = 1;
[136]272
[224]273 desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptor : (const uint8_t*)&USB_DeviceDescriptor;
[136]274
[224]275 if (*desc_addr > setup.wLength) {
276 desc_length = setup.wLength;
277 }
[136]278 }
[224]279 else if (USB_STRING_DESCRIPTOR_TYPE == t)
[136]280 {
[224]281 if (setup.wValueL == 0) {
282 desc_addr = (const uint8_t*)&STRING_LANGUAGE;
283 }
284 else if (setup.wValueL == IPRODUCT) {
285 return USBD_SendStringDescriptor(STRING_PRODUCT, setup.wLength);
286 }
287 else if (setup.wValueL == IMANUFACTURER) {
288 return USBD_SendStringDescriptor(STRING_MANUFACTURER, setup.wLength);
289 }
290 else {
291 return false;
292 }
293 if (*desc_addr > setup.wLength) {
294 desc_length = setup.wLength;
295 }
[136]296 }
[224]297 else
[136]298 {
299 }
300
[224]301 if (desc_addr == 0) {
302 return false;
[136]303 }
304
[224]305 if (desc_length == 0) {
306 desc_length = *desc_addr;
[136]307 }
[224]308
309 USBD_SendControl(desc_addr, desc_length);
310
[136]311 return true;
312}
313
[224]314void initEP(uint32_t ep, uint32_t config)
[136]315{
[224]316 if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)))
[136]317 {
[224]318 usbd.epBank1SetSize(ep, 64);
319 usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
320 usbd.epBank1SetType(ep, 4); // INTERRUPT IN
[136]321 }
[224]322 else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0)))
323 {
324 usbd.epBank0SetSize(ep, 64);
325 usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
326 usbd.epBank0SetType(ep, 3); // BULK OUT
[136]327
[224]328 // Release OUT EP
329 usbd.epBank0SetMultiPacketSize(ep, 64);
330 usbd.epBank0SetByteCount(ep, 0);
331 }
332 else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)))
[136]333 {
[224]334 usbd.epBank1SetSize(ep, 64);
335 usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
336
337 // NAK on endpoint IN, the bank is not yet filled in.
338 usbd.epBank1ResetReady(ep);
339
340 usbd.epBank1SetType(ep, 3); // BULK IN
[136]341 }
[224]342 else if (config == USB_ENDPOINT_TYPE_CONTROL)
[136]343 {
[224]344 // XXX: Needed?
345// usbd.epBank0DisableAutoZLP(ep);
346// usbd.epBank1DisableAutoZLP(ep);
[136]347
[224]348 // Setup Control OUT
349 usbd.epBank0SetSize(ep, 64);
350 usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
351 usbd.epBank0SetType(ep, 1); // CONTROL OUT / SETUP
[136]352
[224]353 // Setup Control IN
354 usbd.epBank1SetSize(ep, 64);
355 usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[0]);
356 usbd.epBank1SetType(ep, 1); // CONTROL IN
357
358 // Release OUT EP
359 usbd.epBank0SetMultiPacketSize(ep, 64);
360 usbd.epBank0SetByteCount(ep, 0);
361
362 // NAK on endpoint OUT, the bank is full.
363 usbd.epBank0SetReady(ep);
[136]364 }
[224]365}
366
367void sendZlp(uint32_t ep)
368{
369 // Set the byte count as zero
370 usbd.epBank1SetByteCount(ep, 0);
371}
372
373void setAddress(uint32_t addr)
374{
375 usbd.epBank1SetByteCount(0, 0);
376 usbd.epBank1AckTransferComplete(0);
377
378 // RAM buffer is full, we can send data (IN)
379 usbd.epBank1SetReady(0);
380
381 // Wait for transfer to complete
382 while (!usbd.epBank1IsTransferComplete(0)) {}
383
384 // Set USB address to addr
385 USB->DEVICE.DADD.bit.DADD = addr; // Address
386 USB->DEVICE.DADD.bit.ADDEN = 1; // Enable
387}
388
389uint32_t EndPoints[] =
390{
391 USB_ENDPOINT_TYPE_CONTROL,
392
393#ifdef CDC_ENABLED
394 USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_ACM
395 USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0), // CDC_ENDPOINT_OUT
396 USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_IN
[136]397#endif
398
[224]399};
400
401void initEndpoints() {
402 for (uint8_t i = 1; i < sizeof(EndPoints) && EndPoints[i] != 0; i++) {
403 initEP(i, EndPoints[i]);
[136]404 }
[224]405}
406
407bool handleStandardSetup(Setup &setup)
408{
409 switch (setup.bRequest) {
410 case GET_STATUS:
411 if (setup.bmRequestType == 0) // device
412 {
413 // Send the device status
414 // TODO: Check current configuration for power mode (if device is configured)
415 // TODO: Check if remote wake-up is enabled
416 uint8_t buff[] = { 0, 0 };
417 USBD_armSend(0, buff, 2);
418 return true;
[136]419 }
[224]420 // if( setup.bmRequestType == 2 ) // Endpoint:
421 else
422 {
423 // Send the endpoint status
424 // Check if the endpoint if currently halted
425 uint8_t buff[] = { 0, 0 };
426 if (isEndpointHalt == 1)
427 buff[0] = 1;
428 USBD_armSend(0, buff, 2);
429 return true;
[136]430 }
[224]431
432 case CLEAR_FEATURE:
433 // Check which is the selected feature
434 if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP
435 {
436 // Enable remote wake-up and send a ZLP
437 uint8_t buff[] = { 0, 0 };
438 if (isRemoteWakeUpEnabled == 1)
439 buff[0] = 1;
440 USBD_armSend(0, buff, 2);
441 return true;
[136]442 }
[224]443 else // if( setup.wValueL == 0) // ENDPOINTHALT
444 {
445 isEndpointHalt = 0;
446 sendZlp(0);
447 return true;
[136]448 }
[224]449
450 case SET_FEATURE:
451 // Check which is the selected feature
452 if (setup.wValueL == 1) // DEVICEREMOTEWAKEUP
453 {
454 // Enable remote wake-up and send a ZLP
455 isRemoteWakeUpEnabled = 1;
456 uint8_t buff[] = { 0 };
457 USBD_armSend(0, buff, 1);
458 return true;
[136]459 }
[224]460 if (setup.wValueL == 0) // ENDPOINTHALT
461 {
462 // Halt endpoint
463 isEndpointHalt = 1;
464 sendZlp(0);
465 return true;
466 }
[136]467
[224]468 case SET_ADDRESS:
469 setAddress(setup.wValueL);
470 return true;
471
472 case GET_DESCRIPTOR:
473 return USBD_SendDescriptor(setup);
474
475 case SET_DESCRIPTOR:
[136]476 return false;
[224]477
478 case GET_CONFIGURATION:
479 USBD_armSend(0, (void*)&_usbConfiguration, 1);
480 return true;
481
482 case SET_CONFIGURATION:
483 if (REQUEST_DEVICE == (setup.bmRequestType & REQUEST_RECIPIENT)) {
484
485 initEndpoints();
486 _usbConfiguration = setup.wValueL;
487
488 #if defined(CDC_ENABLED)
489 // Enable interrupt for CDC reception from host (OUT packet)
490 usbd.epBank1EnableTransferComplete(CDC_ENDPOINT_ACM);
491 usbd.epBank0EnableTransferComplete(CDC_ENDPOINT_OUT);
492 #endif
493
494 sendZlp(0);
495 return true;
496 } else {
497 return false;
498 }
499
500 case GET_INTERFACE:
501 USBD_armSend(0, (void*)&_usbSetInterface, 1);
502 return true;
503
504 case SET_INTERFACE:
505 _usbSetInterface = setup.wValueL;
506 sendZlp(0);
507 return true;
508
509 default:
510 return true;
[136]511 }
[224]512}
[136]513
[224]514bool handleClassInterfaceSetup(Setup& setup)
515{
516 uint8_t i = setup.wIndex;
517
518 #if defined(CDC_ENABLED)
519 if (CDC_ACM_INTERFACE == i)
[136]520 {
[224]521 if (CDC_Setup(setup) == false) {
522 sendZlp(0);
523 }
524 return true;
[136]525 }
[224]526 #endif
[136]527
[224]528 return false;
529}
[136]530
[224]531void stall(uint32_t ep)
532{
533 // TODO: test
534 // TODO: use .bit. notation
535
536 // Stall endpoint
537 USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ(2);
[136]538}
539
[224]540void handleEndpoint(uint8_t ep)
[136]541{
[224]542#if defined(CDC_ENABLED)
543 if (ep == CDC_ENDPOINT_OUT)
[136]544 {
[224]545 // The RAM Buffer is empty: we can receive data
546 //usbd.epBank0ResetReady(CDC_ENDPOINT_OUT);
[136]547
[224]548 // Handle received bytes
[136]549 if (USBD_Available(CDC_ENDPOINT_OUT))
550 SerialUSB.accept();
551 }
[224]552 if (ep == CDC_ENDPOINT_IN)
[136]553 {
[224]554 // NAK on endpoint IN, the bank is not yet filled in.
555 usbd.epBank1ResetReady(CDC_ENDPOINT_IN);
556 usbd.epBank1AckTransferComplete(CDC_ENDPOINT_IN);
[136]557 }
[224]558 if (ep == CDC_ENDPOINT_ACM)
[136]559 {
[224]560 // NAK on endpoint IN, the bank is not yet filled in.
561 usbd.epBank1ResetReady(CDC_ENDPOINT_ACM);
562 usbd.epBank1AckTransferComplete(CDC_ENDPOINT_ACM);
[136]563 }
564#endif
565
566}
567
[224]568void ISRHandler()
[136]569{
570
[224]571 if (_pack_message == true) {
572 return;
573 }
574 // End-Of-Reset
575 if (usbd.isEndOfResetInterrupt())
[136]576 {
[224]577 // Configure EP 0
578 initEP(0, USB_ENDPOINT_TYPE_CONTROL);
[136]579
[224]580 // Enable Setup-Received interrupt
581 usbd.epBank0EnableSetupReceived(0);
582
583 _usbConfiguration = 0;
584
585 usbd.ackEndOfResetInterrupt();
586 }
587
588 // Start-Of-Frame
589 if (usbd.isStartOfFrameInterrupt())
590 {
591 usbd.ackStartOfFrameInterrupt();
592 }
593
594 // Endpoint 0 Received Setup interrupt
595 if (usbd.epBank0IsSetupReceived(0))
596 {
597 usbd.epBank0AckSetupReceived(0);
598
599 Setup *setup = reinterpret_cast<Setup *>(udd_ep_out_cache_buffer[0]);
600
601 /* Clear the Bank 0 ready flag on Control OUT */
602 // The RAM Buffer is empty: we can receive data
603 usbd.epBank0ResetReady(0);
604
605 bool ok;
606 if (REQUEST_STANDARD == (setup->bmRequestType & REQUEST_TYPE)) {
607 // Standard Requests
608 ok = handleStandardSetup(*setup);
609 } else {
610 // Class Interface Requests
611 ok = handleClassInterfaceSetup(*setup);
612 }
613
614 if (ok) {
615 usbd.epBank1SetReady(0);
616 } else {
617 stall(0);
618 }
619
620 if (usbd.epBank1IsStalled(0))
[136]621 {
[224]622 usbd.epBank1AckStalled(0);
[136]623
[224]624 // Remove stall request
625 usbd.epBank1DisableStalled(0);
[136]626 }
[224]627
628 } // end Received Setup handler
629 PORT->Group[0].OUTSET.reg =0x08000000 ; //TxLED off
630 PORT->Group[1].OUTSET.reg =0x00000008 ; //RxLED off
[136]631
[224]632 uint8_t i=0;
633 uint8_t ept_int = usbd.epInterruptSummary() & 0xFE; // Remove endpoint number 0 (setup)
634 while (ept_int != 0)
635 {
636 // Check if endpoint has a pending interrupt
637 if ((ept_int & (1 << i)) != 0)
[136]638 {
[224]639 // Endpoint Transfer Complete (0/1) Interrupt
640 if (usbd.epBank0IsTransferComplete(i) ||
641 usbd.epBank1IsTransferComplete(i))
642 {
643 handleEndpoint(i);
644 }
645 ept_int &= ~(1 << i);
[136]646 }
[224]647 i++;
648 if (i > USB_EPT_NUM)
649 break; // fire exit
650 }
651}
[136]652
[224]653// USB_Handler ISR
654extern "C" void UDD_Handler(void) {
655 ISRHandler();
656}
657
658
659void USBD_Flush(uint32_t ep)
660{
661 if (USBD_Available(ep)) {
662 // RAM buffer is full, we can send data (IN)
663 usbd.epBank1SetReady(ep);
664
665 // Clear the transfer complete flag
666 usbd.epBank1AckTransferComplete(ep);
[136]667 }
[224]668}
[136]669
670
[224]671bool connected()
672{
673 // Count frame numbers
674 uint8_t f = USB->DEVICE.FNUM.bit.FNUM;
675 //delay(3);
676 return f != USB->DEVICE.FNUM.bit.FNUM;
677}
[136]678
[224]679uint8_t armRecvCtrlOUT(uint32_t ep)
680{
681 // Get endpoint configuration from setting register
682 usbd.epBank0SetAddress(ep, &udd_ep_out_cache_buffer[ep]);
683 usbd.epBank0SetMultiPacketSize(ep, 8);
684 usbd.epBank0SetByteCount(ep, 0);
[136]685
[224]686 usbd.epBank0ResetReady(ep);
[136]687
[224]688 // Wait OUT
689 while (!usbd.epBank0IsReady(ep)) {}
690 while (!usbd.epBank0IsTransferComplete(ep)) {}
691 return usbd.epBank0ByteCount(ep);
692}
[136]693
694
[224]695uint32_t USBD_RecvControl(void *_data, uint32_t len)
696{
697 uint8_t *data = reinterpret_cast<uint8_t *>(_data);
[136]698
[224]699 // The RAM Buffer is empty: we can receive data
700 usbd.epBank0ResetReady(0);
[136]701
[224]702 //usbd.epBank0AckSetupReceived(0);
703 uint32_t read = armRecvCtrlOUT(0);
704 if (read > len)
705 read = len;
706 //while (!usbd.epBank0AckTransferComplete(0)) {}
707 uint8_t *buffer = udd_ep_out_cache_buffer[0];
708 for (uint32_t i=0; i<len; i++) {
709 data[i] = buffer[i];
710 }
[136]711
[224]712 return read;
713}
[136]714
[224]715// Number of bytes, assumes a rx endpoint
716uint32_t USBD_Available(uint32_t ep)
717{
718 return usbd.epBank0ByteCount(ep);
719}
[136]720
[224]721uint8_t armRecv(uint32_t ep)
722{
723 uint16_t count = usbd.epBank0ByteCount(ep);
724 if (count >= 64) {
725 usbd.epBank0SetByteCount(ep, count - 64);
726 } else {
727 usbd.epBank0SetByteCount(ep, 0);
[136]728 }
[224]729 return usbd.epBank0ByteCount(ep);
[136]730}
731
[224]732// Non Blocking receive
733// Return number of bytes read
734uint32_t USBD_Recv(uint32_t ep, void *_data, uint32_t len)
735{
736 if (!_usbConfiguration)
737 return -1;
[136]738
[224]739 PORT->Group[1].OUTCLR.reg =0x00000008 ; //RxLED on
740 if (USBD_Available(ep) < len)
741 len = USBD_Available(ep);
[136]742
[224]743 armRecv(ep);
744
745 usbd.epBank0DisableTransferComplete(ep);
746
747 memcpy(_data, udd_ep_out_cache_buffer[ep], len);
748
749 // release empty buffer
750 if (len && !USBD_Available(ep)) {
751 // The RAM Buffer is empty: we can receive data
752 usbd.epBank0ResetReady(ep);
753
754 // Clear Transfer complete 0 flag
755 usbd.epBank0AckTransferComplete(ep);
[136]756 }
[224]757
758 return len;
[136]759}
760
[224]761// Recv 1 byte if ready
762uint32_t USBD_Recv(uint32_t ep)
[136]763{
[224]764 uint8_t c;
765 if (USBD_Recv(ep, &c, 1) != 1) {
766 return -1;
767 } else {
768 return c;
769 }
[136]770}
771
772
773
[224]774//==================================================================
[136]775
[224]776void USBDevice_::init()
[136]777{
[224]778 // Enable USB clock
779 PM->APBBMASK.reg |= PM_APBBMASK_USB;
780
781 // Set up the USB DP/DN pins
782 PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
783 PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
784 PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
785 PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
786 PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
787 PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
788
789 // Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
790 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | // Generic Clock Multiplexer 6
791 GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
792 GCLK_CLKCTRL_CLKEN;
793 while (GCLK->STATUS.bit.SYNCBUSY)
794 ;
795
796 USB_SetHandler(&UDD_Handler);
797
798 // Reset USB Device
799 usbd.reset();
800
801 usbd.calibrate();
802 usbd.setUSBDeviceMode();
803 usbd.runInStandby();
804 usbd.setFullSpeed();
805
806 // Configure interrupts
807 NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
808 NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
809
810 usbd.enable();
811
812 initialized = true;
[136]813}
814
815bool USBDevice_::attach()
816{
[224]817 if (!initialized)
818 return false;
819
820 usbd.attach();
821 usbd.enableEndOfResetInterrupt();
822 usbd.enableStartOfFrameInterrupt();
823
[136]824 _usbConfiguration = 0;
825 return true;
826}
827
[224]828
[136]829bool USBDevice_::detach()
830{
[224]831 if (!initialized)
[136]832 return false;
[224]833 usbd.detach();
834 return true;
[136]835}
836
837bool USBDevice_::configured()
838{
[224]839 return _usbConfiguration != 0;
[136]840}
841
842
[224]843
844/*
845 * USB Device instance
846 * -------------------
847 */
848
849// USBDevice class instance
850USBDevice_ USBDevice;
Note: See TracBrowser for help on using the repository browser.