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

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

1.7.10のファイルに更新

File size: 18.5 KB
Line 
1/*
2 Copyright (c) 2015 Arduino LLC. All right reserved.
3
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.
8
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.
13
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*/
18/*
19**Modified 04/04/2016 by Arduino.org development team
20*/
21
22#include <Arduino.h>
23
24#include "SAMD21_USBDevice.h"
25#include "USB_host.h"
26
27#include <stdlib.h>
28#include <stdio.h>
29#include <stdint.h>
30#include <limits.h>
31
32USBDevice_SAMD21G18x usbd;
33
34static char isRemoteWakeUpEnabled = 0;
35static char isEndpointHalt = 0;
36
37extern void (*gpf_isr)(void);
38
39
40const uint16_t STRING_LANGUAGE[2] = {
41 (3<<8) | (2+2),
42 0x0409 // English
43};
44
45#define USB_PID_ZERO_PRO 0x804d
46#define USB_PRODUCT "Arduino M0 Pro"
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
82
83//==================================================================
84
85volatile uint32_t _usbConfiguration = 0;
86volatile uint32_t _usbSetInterface = 0;
87
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
94//==================================================================
95
96bool _dry_run = false;
97bool _pack_message = false;
98uint16_t _pack_size = 0;
99uint8_t _pack_buffer[256];
100
101
102void packMessages(bool val)
103{
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 }
111}
112
113// Blocking Send of data to an endpoint
114uint32_t USBD_Send(uint32_t ep, const void *data, uint32_t len)
115{
116 uint32_t length = 0;
117
118 if (!_usbConfiguration)
119 return -1;
120 if (len > 16384)
121 return -1;
122
123 PORT->Group[0].OUTCLR.reg =0x08000000 ; //TxLED on
124 // Flash area
125 while (len != 0)
126 {
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;
152 }
153 return len;
154}
155
156uint32_t USBD_armSend(uint32_t ep, const void* data, uint32_t len)
157{
158 memcpy(&udd_ep_in_cache_buffer[ep], data, len);
159
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);
164
165 return len;
166}
167
168uint32_t USBD_SendControl(const void* _data, uint32_t len)
169{
170 const uint8_t *data = reinterpret_cast<const uint8_t *>(_data);
171 uint32_t length = len;
172 uint32_t sent = 0;
173 uint32_t pos = 0;
174
175 if (_dry_run == true)
176 return length;
177
178 if (_pack_message == true) {
179 memcpy(&_pack_buffer[_pack_size], data, len);
180 _pack_size += len;
181 return length;
182 }
183
184 while (len > 0)
185 {
186 sent = USBD_armSend(EP0, data + pos, len);
187 pos += sent;
188 len -= sent;
189 }
190
191 return length;
192}
193
194bool USBD_SendStringDescriptor(const uint8_t *string, uint8_t maxlen)
195{
196 if (maxlen < 2)
197 return false;
198
199 uint16_t buff[maxlen/2];
200 int l = 1;
201
202 maxlen -= 2;
203 while (*string && maxlen>0)
204 {
205 buff[l++] = (uint8_t)(*string++);
206 maxlen -= 2;
207 }
208 buff[0] = (3<<8) | (l*2);
209
210 return USBD_SendControl((uint8_t*)buff, l*2);
211}
212
213uint8_t USBD_SendInterfaces(uint32_t* total)
214{
215 uint8_t interfaces = 0;
216
217#if defined(CDC_ENABLED)
218 total[0] += CDC_GetInterface(&interfaces);
219#endif
220
221 return interfaces;
222}
223
224// Construct a dynamic configuration descriptor
225// This really needs dynamic endpoint allocation etc
226uint32_t USBD_SendConfiguration(uint32_t maxlen)
227{
228 uint32_t total = 0;
229 // Count and measure interfaces
230 _dry_run = true;
231 uint8_t interfaces = USBD_SendInterfaces(&total);
232
233 _Pragma("pack(1)")
234 ConfigDescriptor config = D_CONFIG((uint16_t)(total + sizeof(ConfigDescriptor)), interfaces);
235 _Pragma("pack()")
236
237 // Now send them
238 _dry_run = false;
239
240 if (maxlen == sizeof(ConfigDescriptor)) {
241 USBD_SendControl(&config, sizeof(ConfigDescriptor));
242 return true;
243 }
244
245 total = 0;
246
247 packMessages(true);
248 USBD_SendControl(&config, sizeof(ConfigDescriptor));
249 USBD_SendInterfaces(&total);
250 packMessages(false);
251
252 return true;
253}
254
255bool USBD_SendDescriptor(Setup &setup)
256{
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;
262
263 if (t == USB_CONFIGURATION_DESCRIPTOR_TYPE)
264 {
265 return USBD_SendConfiguration(setup.wLength);
266 }
267
268 if (t == USB_DEVICE_DESCRIPTOR_TYPE)
269 {
270 if (setup.wLength == 8)
271 _cdcComposite = 1;
272
273 desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptor : (const uint8_t*)&USB_DeviceDescriptor;
274
275 if (*desc_addr > setup.wLength) {
276 desc_length = setup.wLength;
277 }
278 }
279 else if (USB_STRING_DESCRIPTOR_TYPE == t)
280 {
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 }
296 }
297 else
298 {
299 }
300
301 if (desc_addr == 0) {
302 return false;
303 }
304
305 if (desc_length == 0) {
306 desc_length = *desc_addr;
307 }
308
309 USBD_SendControl(desc_addr, desc_length);
310
311 return true;
312}
313
314void initEP(uint32_t ep, uint32_t config)
315{
316 if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)))
317 {
318 usbd.epBank1SetSize(ep, 64);
319 usbd.epBank1SetAddress(ep, &udd_ep_in_cache_buffer[ep]);
320 usbd.epBank1SetType(ep, 4); // INTERRUPT IN
321 }
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
327
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)))
333 {
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
341 }
342 else if (config == USB_ENDPOINT_TYPE_CONTROL)
343 {
344 // XXX: Needed?
345// usbd.epBank0DisableAutoZLP(ep);
346// usbd.epBank1DisableAutoZLP(ep);
347
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
352
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);
364 }
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
397#endif
398
399};
400
401void initEndpoints() {
402 for (uint8_t i = 1; i < sizeof(EndPoints) && EndPoints[i] != 0; i++) {
403 initEP(i, EndPoints[i]);
404 }
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;
419 }
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;
430 }
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;
442 }
443 else // if( setup.wValueL == 0) // ENDPOINTHALT
444 {
445 isEndpointHalt = 0;
446 sendZlp(0);
447 return true;
448 }
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;
459 }
460 if (setup.wValueL == 0) // ENDPOINTHALT
461 {
462 // Halt endpoint
463 isEndpointHalt = 1;
464 sendZlp(0);
465 return true;
466 }
467
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:
476 return false;
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;
511 }
512}
513
514bool handleClassInterfaceSetup(Setup& setup)
515{
516 uint8_t i = setup.wIndex;
517
518 #if defined(CDC_ENABLED)
519 if (CDC_ACM_INTERFACE == i)
520 {
521 if (CDC_Setup(setup) == false) {
522 sendZlp(0);
523 }
524 return true;
525 }
526 #endif
527
528 return false;
529}
530
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);
538}
539
540void handleEndpoint(uint8_t ep)
541{
542#if defined(CDC_ENABLED)
543 if (ep == CDC_ENDPOINT_OUT)
544 {
545 // The RAM Buffer is empty: we can receive data
546 //usbd.epBank0ResetReady(CDC_ENDPOINT_OUT);
547
548 // Handle received bytes
549 if (USBD_Available(CDC_ENDPOINT_OUT))
550 SerialUSB.accept();
551 }
552 if (ep == CDC_ENDPOINT_IN)
553 {
554 // NAK on endpoint IN, the bank is not yet filled in.
555 usbd.epBank1ResetReady(CDC_ENDPOINT_IN);
556 usbd.epBank1AckTransferComplete(CDC_ENDPOINT_IN);
557 }
558 if (ep == CDC_ENDPOINT_ACM)
559 {
560 // NAK on endpoint IN, the bank is not yet filled in.
561 usbd.epBank1ResetReady(CDC_ENDPOINT_ACM);
562 usbd.epBank1AckTransferComplete(CDC_ENDPOINT_ACM);
563 }
564#endif
565
566}
567
568void ISRHandler()
569{
570
571 if (_pack_message == true) {
572 return;
573 }
574 // End-Of-Reset
575 if (usbd.isEndOfResetInterrupt())
576 {
577 // Configure EP 0
578 initEP(0, USB_ENDPOINT_TYPE_CONTROL);
579
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))
621 {
622 usbd.epBank1AckStalled(0);
623
624 // Remove stall request
625 usbd.epBank1DisableStalled(0);
626 }
627
628 } // end Received Setup handler
629 PORT->Group[0].OUTSET.reg =0x08000000 ; //TxLED off
630 PORT->Group[1].OUTSET.reg =0x00000008 ; //RxLED off
631
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)
638 {
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);
646 }
647 i++;
648 if (i > USB_EPT_NUM)
649 break; // fire exit
650 }
651}
652
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);
667 }
668}
669
670
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}
678
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);
685
686 usbd.epBank0ResetReady(ep);
687
688 // Wait OUT
689 while (!usbd.epBank0IsReady(ep)) {}
690 while (!usbd.epBank0IsTransferComplete(ep)) {}
691 return usbd.epBank0ByteCount(ep);
692}
693
694
695uint32_t USBD_RecvControl(void *_data, uint32_t len)
696{
697 uint8_t *data = reinterpret_cast<uint8_t *>(_data);
698
699 // The RAM Buffer is empty: we can receive data
700 usbd.epBank0ResetReady(0);
701
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 }
711
712 return read;
713}
714
715// Number of bytes, assumes a rx endpoint
716uint32_t USBD_Available(uint32_t ep)
717{
718 return usbd.epBank0ByteCount(ep);
719}
720
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);
728 }
729 return usbd.epBank0ByteCount(ep);
730}
731
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;
738
739 PORT->Group[1].OUTCLR.reg =0x00000008 ; //RxLED on
740 if (USBD_Available(ep) < len)
741 len = USBD_Available(ep);
742
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);
756 }
757
758 return len;
759}
760
761// Recv 1 byte if ready
762uint32_t USBD_Recv(uint32_t ep)
763{
764 uint8_t c;
765 if (USBD_Recv(ep, &c, 1) != 1) {
766 return -1;
767 } else {
768 return c;
769 }
770}
771
772
773
774//==================================================================
775
776void USBDevice_::init()
777{
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;
813}
814
815bool USBDevice_::attach()
816{
817 if (!initialized)
818 return false;
819
820 usbd.attach();
821 usbd.enableEndOfResetInterrupt();
822 usbd.enableStartOfFrameInterrupt();
823
824 _usbConfiguration = 0;
825 return true;
826}
827
828
829bool USBDevice_::detach()
830{
831 if (!initialized)
832 return false;
833 usbd.detach();
834 return true;
835}
836
837bool USBDevice_::configured()
838{
839 return _usbConfiguration != 0;
840}
841
842
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.