]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/arm_atsam/usb/usb.c
Massdrop keyboard support (#3780)
[qmk_firmware.git] / tmk_core / protocol / arm_atsam / usb / usb.c
1 /**
2  * \file
3  *
4  * \brief SAM USB Driver.
5  *
6  * Copyright (C) 2014-2016 Atmel Corporation. All rights reserved.
7  *
8  * \asf_license_start
9  *
10  * \page License
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  *    this list of conditions and the following disclaimer in the documentation
20  *    and/or other materials provided with the distribution.
21  *
22  * 3. The name of Atmel may not be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * 4. This software may only be redistributed and used in connection with an
26  *    Atmel microcontroller product.
27  *
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  *
40  * \asf_license_stop
41  *
42  */
43 /*
44  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45  */
46
47 #define DEVICE_MODE_ONLY true
48 #define SAMD11 DEVICE_MODE_ONLY
49
50 #ifndef ARM_MATH_CM4
51   #define ARM_MATH_CM4
52 #endif
53
54 #include "compiler.h"
55 #undef LITTLE_ENDIAN  //redefined in samd51j18a.h
56 #include "samd51j18a.h"
57 #include <stdbool.h>
58 #include <string.h>
59 #include "arm_math.h"
60 #include "status_codes.h"
61 #include "usb.h"
62
63 /** Fields definition from a LPM TOKEN  */
64 #define  USB_LPM_ATTRIBUT_BLINKSTATE_MASK      (0xF << 0)
65 #define  USB_LPM_ATTRIBUT_HIRD_MASK            (0xF << 4)
66 #define  USB_LPM_ATTRIBUT_REMOTEWAKE_MASK      (1 << 8)
67 #define  USB_LPM_ATTRIBUT_BLINKSTATE(value)    ((value & 0xF) << 0)
68 #define  USB_LPM_ATTRIBUT_HIRD(value)          ((value & 0xF) << 4)
69 #define  USB_LPM_ATTRIBUT_REMOTEWAKE(value)    ((value & 1) << 8)
70 #define  USB_LPM_ATTRIBUT_BLINKSTATE_L1        USB_LPM_ATTRIBUT_BLINKSTATE(1)
71
72 /**
73  * \brief Mask selecting the index part of an endpoint address
74  */
75 #define  USB_EP_ADDR_MASK     0x0f
76
77 /**
78  * \brief Endpoint transfer direction is IN
79  */
80 #define  USB_EP_DIR_IN        0x80
81
82 /**
83  * \brief Endpoint transfer direction is OUT
84  */
85 #define  USB_EP_DIR_OUT       0x00
86
87 /**
88  * \name USB SRAM data containing pipe descriptor table
89  * The content of the USB SRAM can be :
90  * - modified by USB hardware interface to update pipe status.
91  *   Thereby, it is read by software.
92  * - modified by USB software to control pipe.
93  *   Thereby, it is read by hardware.
94  * This data section is volatile.
95  *
96  * @{
97  */
98 COMPILER_PACK_SET(1)
99 COMPILER_WORD_ALIGNED
100 union {
101     UsbDeviceDescriptor usb_endpoint_table[USB_EPT_NUM];
102 } usb_descriptor_table;
103 COMPILER_PACK_RESET()
104 /** @} */
105
106 /**
107  * \brief Local USB module instance
108  */
109 static struct usb_module *_usb_instances;
110
111 /* Device LPM callback variable */
112 static uint32_t device_callback_lpm_wakeup_enable;
113
114 /**
115  * \brief Device endpoint callback parameter variable, used to transfer info to UDD wrapper layer
116  */
117 static struct usb_endpoint_callback_parameter ep_callback_para;
118
119 /**
120  * \internal USB Device IRQ Mask Bits Map
121  */
122 static const uint16_t _usb_device_irq_bits[USB_DEVICE_CALLBACK_N] = {
123     USB_DEVICE_INTFLAG_SOF,
124     USB_DEVICE_INTFLAG_EORST,
125     USB_DEVICE_INTFLAG_WAKEUP | USB_DEVICE_INTFLAG_EORSM | USB_DEVICE_INTFLAG_UPRSM,
126     USB_DEVICE_INTFLAG_RAMACER,
127     USB_DEVICE_INTFLAG_SUSPEND,
128     USB_DEVICE_INTFLAG_LPMNYET,
129     USB_DEVICE_INTFLAG_LPMSUSP,
130 };
131
132 /**
133  * \internal USB Device IRQ Mask Bits Map
134  */
135 static const uint8_t _usb_endpoint_irq_bits[USB_DEVICE_EP_CALLBACK_N] = {
136     USB_DEVICE_EPINTFLAG_TRCPT_Msk,
137     USB_DEVICE_EPINTFLAG_TRFAIL_Msk,
138     USB_DEVICE_EPINTFLAG_RXSTP,
139     USB_DEVICE_EPINTFLAG_STALL_Msk
140 };
141
142 /**
143  * \brief Registers a USB device callback
144  *
145  * Registers a callback function which is implemented by the user.
146  *
147  * \note The callback must be enabled by \ref usb_device_enable_callback,
148  * in order for the interrupt handler to call it when the conditions for the
149  * callback type is met.
150  *
151  * \param[in]     module_inst   Pointer to USB software instance struct
152  * \param[in]     callback_type Callback type given by an enum
153  * \param[in]     callback_func Pointer to callback function
154  *
155  * \return Status of the registration operation.
156  * \retval STATUS_OK    The callback was registered successfully.
157  */
158 enum status_code usb_device_register_callback(struct usb_module *module_inst,
159         enum usb_device_callback callback_type,
160         usb_device_callback_t callback_func)
161 {
162     /* Sanity check arguments */
163     Assert(module_inst);
164     Assert(callback_func);
165
166     /* Register callback function */
167     module_inst->device_callback[callback_type] = callback_func;
168
169     /* Set the bit corresponding to the callback_type */
170     module_inst->device_registered_callback_mask |= _usb_device_irq_bits[callback_type];
171
172     return STATUS_OK;
173 }
174
175 /**
176  * \brief Unregisters a USB device callback
177  *
178  * Unregisters an asynchronous callback implemented by the user. Removing it
179  * from the internal callback registration table.
180  *
181  * \param[in]     module_inst   Pointer to USB software instance struct
182  * \param[in]     callback_type Callback type given by an enum
183  *
184  * \return Status of the de-registration operation.
185  * \retval STATUS_OK    The callback was unregistered successfully.
186  */
187 enum status_code usb_device_unregister_callback(struct usb_module *module_inst,
188         enum usb_device_callback callback_type)
189 {
190     /* Sanity check arguments */
191     Assert(module_inst);
192
193     /* Unregister callback function */
194     module_inst->device_callback[callback_type] = NULL;
195
196     /* Clear the bit corresponding to the callback_type */
197     module_inst->device_registered_callback_mask &= ~_usb_device_irq_bits[callback_type];
198
199     return STATUS_OK;
200 }
201
202 /**
203  * \brief Enables USB device callback generation for a given type.
204  *
205  * Enables asynchronous callbacks for a given logical type.
206  * This must be called before USB device generate callback events.
207  *
208  * \param[in]     module_inst   Pointer to USB software instance struct
209  * \param[in]     callback_type Callback type given by an enum
210  *
211  * \return Status of the callback enable operation.
212  * \retval STATUS_OK    The callback was enabled successfully.
213  */
214 enum status_code usb_device_enable_callback(struct usb_module *module_inst,
215         enum usb_device_callback callback_type)
216 {
217     /* Sanity check arguments */
218     Assert(module_inst);
219     Assert(module_inst->hw);
220
221     /* clear related flag */
222     module_inst->hw->DEVICE.INTFLAG.reg = _usb_device_irq_bits[callback_type];
223
224     /* Enable callback */
225     module_inst->device_enabled_callback_mask |= _usb_device_irq_bits[callback_type];
226
227     module_inst->hw->DEVICE.INTENSET.reg = _usb_device_irq_bits[callback_type];
228
229     return STATUS_OK;
230 }
231
232 /**
233  * \brief Disables USB device callback generation for a given type.
234  *
235  * Disables asynchronous callbacks for a given logical type.
236  *
237  * \param[in]     module_inst   Pointer to USB software instance struct
238  * \param[in]     callback_type Callback type given by an enum
239  *
240  * \return Status of the callback disable operation.
241  * \retval STATUS_OK    The callback was disabled successfully.
242  */
243 enum status_code usb_device_disable_callback(struct usb_module *module_inst,
244         enum usb_device_callback callback_type)
245 {
246     /* Sanity check arguments */
247     Assert(module_inst);
248     Assert(module_inst->hw);
249
250     /* Disable callback */
251     module_inst->device_enabled_callback_mask &= ~_usb_device_irq_bits[callback_type];
252
253     module_inst->hw->DEVICE.INTENCLR.reg = _usb_device_irq_bits[callback_type];
254
255     return STATUS_OK;
256 }
257
258 /**
259  * \brief Registers a USB device endpoint callback
260  *
261  * Registers a callback function which is implemented by the user.
262  *
263  * \note The callback must be enabled by \ref usb_device_endpoint_enable_callback,
264  * in order for the interrupt handler to call it when the conditions for the
265  * callback type is met.
266  *
267  * \param[in]     module_inst   Pointer to USB software instance struct
268  * \param[in]     ep_num        Endpoint to configure
269  * \param[in]     callback_type Callback type given by an enum
270  * \param[in]     callback_func Pointer to callback function
271  *
272  * \return Status of the registration operation.
273  * \retval STATUS_OK    The callback was registered successfully.
274  */
275 enum status_code usb_device_endpoint_register_callback(
276         struct usb_module *module_inst, uint8_t ep_num,
277         enum usb_device_endpoint_callback callback_type,
278         usb_device_endpoint_callback_t callback_func)
279 {
280     /* Sanity check arguments */
281     Assert(module_inst);
282     Assert(ep_num < USB_EPT_NUM);
283     Assert(callback_func);
284
285     /* Register callback function */
286     module_inst->device_endpoint_callback[ep_num][callback_type] = callback_func;
287
288     /* Set the bit corresponding to the callback_type */
289     module_inst->device_endpoint_registered_callback_mask[ep_num] |= _usb_endpoint_irq_bits[callback_type];
290
291     return STATUS_OK;
292 }
293
294 /**
295  * \brief Unregisters a USB device endpoint callback
296  *
297  * Unregisters an callback implemented by the user. Removing it
298  * from the internal callback registration table.
299  *
300  * \param[in]     module_inst   Pointer to USB software instance struct
301  * \param[in]     ep_num        Endpoint to configure
302  * \param[in]     callback_type Callback type given by an enum
303  *
304  * \return Status of the de-registration operation.
305  * \retval STATUS_OK    The callback was unregistered successfully.
306  */
307 enum status_code usb_device_endpoint_unregister_callback(
308         struct usb_module *module_inst, uint8_t ep_num,
309         enum usb_device_endpoint_callback callback_type)
310 {
311     /* Sanity check arguments */
312     Assert(module_inst);
313     Assert(ep_num < USB_EPT_NUM);
314
315     /* Unregister callback function */
316     module_inst->device_endpoint_callback[ep_num][callback_type] = NULL;
317
318     /* Clear the bit corresponding to the callback_type */
319     module_inst->device_endpoint_registered_callback_mask[ep_num] &= ~_usb_endpoint_irq_bits[callback_type];
320
321     return STATUS_OK;
322 }
323
324 /**
325  * \brief Enables USB device endpoint callback generation for a given type.
326  *
327  * Enables callbacks for a given logical type.
328  * This must be called before USB device pipe generate callback events.
329  *
330  * \param[in]     module_inst   Pointer to USB software instance struct
331  * \param[in]     ep            Endpoint to configure
332  * \param[in]     callback_type Callback type given by an enum
333  *
334  * \return Status of the callback enable operation.
335  * \retval STATUS_OK    The callback was enabled successfully.
336  */
337 enum status_code usb_device_endpoint_enable_callback(
338         struct usb_module *module_inst, uint8_t ep,
339         enum usb_device_endpoint_callback callback_type)
340 {
341     /* Sanity check arguments */
342     Assert(module_inst);
343     Assert(module_inst->hw);
344
345     uint8_t ep_num = ep & USB_EP_ADDR_MASK;
346     Assert(ep_num < USB_EPT_NUM);
347
348     /* Enable callback */
349     module_inst->device_endpoint_enabled_callback_mask[ep_num] |= _usb_endpoint_irq_bits[callback_type];
350
351     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRCPT) {
352         if (ep_num == 0) { // control endpoint
353             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0 | USB_DEVICE_EPINTENSET_TRCPT1;
354         } else if (ep & USB_EP_DIR_IN) {
355             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT1;
356         } else {
357             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRCPT0;
358         }
359     }
360
361     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL) {
362         if (ep_num == 0) { // control endpoint
363             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRFAIL0 | USB_DEVICE_EPINTENSET_TRFAIL1;
364         } else if (ep & USB_EP_DIR_IN) {
365             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRFAIL1;
366         } else {
367             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_TRFAIL0;
368         }
369     }
370
371     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_RXSTP) {
372         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_RXSTP;
373     }
374
375     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_STALL) {
376         if (ep & USB_EP_DIR_IN) {
377             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_STALL1;
378         } else {
379             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENSET.reg = USB_DEVICE_EPINTENSET_STALL0;
380         }
381     }
382
383     return STATUS_OK;
384 }
385
386 /**
387  * \brief Disables USB device endpoint callback generation for a given type.
388  *
389  * Disables callbacks for a given logical type.
390  *
391  * \param[in]     module_inst   Pointer to USB software instance struct
392  * \param[in]     ep            Endpoint to configure
393  * \param[in]     callback_type Callback type given by an enum
394  *
395  * \return Status of the callback disable operation.
396  * \retval STATUS_OK    The callback was disabled successfully.
397  */
398 enum status_code usb_device_endpoint_disable_callback(
399         struct usb_module *module_inst, uint8_t ep,
400         enum usb_device_endpoint_callback callback_type)
401 {
402     /* Sanity check arguments */
403     Assert(module_inst);
404     Assert(module_inst->hw);
405
406     uint8_t ep_num = ep & USB_EP_ADDR_MASK;
407     Assert(ep_num < USB_EPT_NUM);
408
409     /* Enable callback */
410     module_inst->device_endpoint_enabled_callback_mask[ep_num] &= ~_usb_endpoint_irq_bits[callback_type];
411
412     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRCPT) {
413         if (ep_num == 0) { // control endpoint
414             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg =  USB_DEVICE_EPINTENCLR_TRCPT0 | USB_DEVICE_EPINTENCLR_TRCPT1;
415         } else if (ep & USB_EP_DIR_IN) {
416             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg =  USB_DEVICE_EPINTENCLR_TRCPT1;
417         } else {
418             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg =  USB_DEVICE_EPINTENCLR_TRCPT0;
419         }
420     }
421
422     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL) {
423         if (ep_num == 0) { // control endpoint
424             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRFAIL0 | USB_DEVICE_EPINTENCLR_TRFAIL1;
425         } else if (ep & USB_EP_DIR_IN) {
426             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRFAIL1;
427         } else {
428             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_TRFAIL0;
429         }
430     }
431
432     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_RXSTP) {
433         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_RXSTP;
434     }
435
436     if (callback_type == USB_DEVICE_ENDPOINT_CALLBACK_STALL) {
437         if (ep & USB_EP_DIR_IN) {
438             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_STALL1;
439         } else {
440             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTENCLR.reg = USB_DEVICE_EPINTENCLR_STALL0;
441         }
442     }
443
444     return STATUS_OK;
445 }
446
447 /**
448  * \brief Initializes an USB device endpoint configuration structure to defaults.
449  *
450  * Initializes a given USB device endpoint configuration structure to a
451  * set of known default values. This function should be called on all new
452  * instances of these configuration structures before being modified by the
453  * user application.
454  *
455  * The default configuration is as follows:
456  * \li endpoint address is 0
457  * \li endpoint size is 8 bytes
458  * \li auto_zlp is false
459  * \li endpoint type is control
460  *
461  * \param[out] ep_config  Configuration structure to initialize to default values
462  */
463 void usb_device_endpoint_get_config_defaults(struct usb_device_endpoint_config *ep_config)
464 {
465     /* Sanity check arguments */
466     Assert(ep_config);
467
468     /* Write default config to config struct */
469     ep_config->ep_address = 0;
470     ep_config->ep_size = USB_ENDPOINT_8_BYTE;
471     ep_config->auto_zlp = false;
472     ep_config->ep_type = USB_DEVICE_ENDPOINT_TYPE_CONTROL;
473 }
474
475 /**
476  * \brief Writes an USB device endpoint configuration to the hardware module.
477  *
478  * Writes out a given configuration of an USB device endpoint
479  * configuration to the hardware module. If the pipe is already configured,
480  * the new configuration will replace the existing one.
481  *
482  * \param[in] module_inst    Pointer to USB software instance struct
483  * \param[in] ep_config      Configuration settings for the endpoint
484  *
485  * \return Status of the device endpoint configuration operation
486  * \retval STATUS_OK         The device endpoint was configured successfully
487  * \retval STATUS_ERR_DENIED The endpoint address is already configured
488  */
489 enum status_code usb_device_endpoint_set_config(struct usb_module *module_inst,
490         struct usb_device_endpoint_config *ep_config)
491 {
492     /* Sanity check arguments */
493     Assert(module_inst);
494     Assert(ep_config);
495
496     uint8_t ep_num = ep_config->ep_address & USB_EP_ADDR_MASK;
497     uint8_t ep_bank = (ep_config->ep_address & USB_EP_DIR_IN) ? 1 : 0;
498
499     switch (ep_config->ep_type) {
500         case USB_DEVICE_ENDPOINT_TYPE_DISABLE:
501             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(0) |  USB_DEVICE_EPCFG_EPTYPE1(0);
502             return STATUS_OK;
503
504         case USB_DEVICE_ENDPOINT_TYPE_CONTROL:
505             if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0 && \
506                 (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0) {
507                 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(1) | USB_DEVICE_EPCFG_EPTYPE1(1);
508                 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
509                 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
510             } else {
511                 return STATUS_ERR_DENIED;
512             }
513             if (true == ep_config->auto_zlp) {
514                 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.reg |= USB_DEVICE_PCKSIZE_AUTO_ZLP;
515                 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.reg |= USB_DEVICE_PCKSIZE_AUTO_ZLP;
516             } else {
517                 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
518                 usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
519             }
520             usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.bit.SIZE = ep_config->ep_size;
521             usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.SIZE = ep_config->ep_size;
522             return STATUS_OK;
523
524         case USB_DEVICE_ENDPOINT_TYPE_ISOCHRONOUS:
525             if (ep_bank) {
526                 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0){
527                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE1(2);
528                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
529                 } else {
530                     return STATUS_ERR_DENIED;
531                 }
532             } else {
533                 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0){
534                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE0(2);
535                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
536                 } else {
537                     return STATUS_ERR_DENIED;
538                 }
539             }
540             break;
541
542         case USB_DEVICE_ENDPOINT_TYPE_BULK:
543             if (ep_bank) {
544                 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0){
545                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE1(3);
546                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
547                 } else {
548                     return STATUS_ERR_DENIED;
549                 }
550             } else {
551                 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0){
552                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE0(3);
553                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
554                 } else {
555                     return STATUS_ERR_DENIED;
556                 }
557             }
558             break;
559
560         case USB_DEVICE_ENDPOINT_TYPE_INTERRUPT:
561             if (ep_bank) {
562                 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE1_Msk) == 0){
563                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE1(4);
564                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
565                 } else {
566                     return STATUS_ERR_DENIED;
567                 }
568             } else {
569                 if ((module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg & USB_DEVICE_EPCFG_EPTYPE0_Msk) == 0){
570                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.reg |= USB_DEVICE_EPCFG_EPTYPE0(4);
571                     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
572                 } else {
573                     return STATUS_ERR_DENIED;
574                 }
575             }
576             break;
577
578         default:
579             break;
580     }
581
582     usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[ep_bank].PCKSIZE.bit.SIZE = ep_config->ep_size;
583
584     if (true == ep_config->auto_zlp) {
585         usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[ep_bank].PCKSIZE.reg |= USB_DEVICE_PCKSIZE_AUTO_ZLP;
586         } else {
587         usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[ep_bank].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
588     }
589
590     return STATUS_OK;
591 }
592
593 /**
594  * \brief Check if current endpoint is configured
595  *
596  * \param module_inst   Pointer to USB software instance struct
597  * \param ep            Endpoint address (direction & number)
598  *
599  * \return \c true if endpoint is configured and ready to use
600  */
601 bool usb_device_endpoint_is_configured(struct usb_module *module_inst, uint8_t ep)
602 {
603     uint8_t ep_num = ep & USB_EP_ADDR_MASK;
604     uint8_t flag;
605
606     if (ep & USB_EP_DIR_IN) {
607         flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE1);
608     } else {
609         flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE0);
610     }
611     return ((enum usb_device_endpoint_type)(flag) != USB_DEVICE_ENDPOINT_TYPE_DISABLE);
612 }
613
614
615 /**
616  * \brief Abort ongoing job on the endpoint
617  *
618  * \param module_inst Pointer to USB software instance struct
619  * \param ep          Endpoint address
620  */
621 void usb_device_endpoint_abort_job(struct usb_module *module_inst, uint8_t ep)
622 {
623     uint8_t ep_num;
624     ep_num = ep & USB_EP_ADDR_MASK;
625
626     // Stop transfer
627     if (ep & USB_EP_DIR_IN) {
628         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
629         // Eventually ack a transfer occur during abort
630         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
631     } else {
632         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
633         // Eventually ack a transfer occur during abort
634         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
635     }
636 }
637
638 /**
639  * \brief Check if endpoint is halted
640  *
641  * \param module_inst Pointer to USB software instance struct
642  * \param ep          Endpoint address
643  *
644  * \return \c true if the endpoint is halted
645  */
646 bool usb_device_endpoint_is_halted(struct usb_module *module_inst, uint8_t ep)
647 {
648     uint8_t ep_num = ep & USB_EP_ADDR_MASK;
649
650     if (ep & USB_EP_DIR_IN) {
651         return (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1);
652     } else {
653         return (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0);
654     }
655 }
656
657 /**
658  * \brief Halt the endpoint (send STALL)
659  *
660  * \param module_inst Pointer to USB software instance struct
661  * \param ep          Endpoint address
662  */
663 void usb_device_endpoint_set_halt(struct usb_module *module_inst, uint8_t ep)
664 {
665     uint8_t ep_num = ep & USB_EP_ADDR_MASK;
666
667     // Stall endpoint
668     if (ep & USB_EP_DIR_IN) {
669         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
670     } else {
671         module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
672     }
673 }
674
675 /**
676  * \brief Clear endpoint halt state
677  *
678  * \param module_inst Pointer to USB software instance struct
679  * \param ep          Endpoint address
680  */
681 void usb_device_endpoint_clear_halt(struct usb_module *module_inst, uint8_t ep)
682 {
683     uint8_t ep_num = ep & USB_EP_ADDR_MASK;
684
685     if (ep & USB_EP_DIR_IN) {
686         if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1) {
687             // Remove stall request
688             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
689             if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL1) {
690                 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL1;
691                 // The Stall has occurred, then reset data toggle
692                 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLIN;
693             }
694         }
695     } else {
696         if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0) {
697             // Remove stall request
698             module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
699             if (module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL0) {
700                 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL0;
701                 // The Stall has occurred, then reset data toggle
702                 module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLOUT;
703             }
704         }
705     }
706 }
707
708 /**
709  * \brief Start write buffer job on a endpoint
710  *
711  * \param module_inst Pointer to USB module instance
712  * \param ep_num      Endpoint number
713  * \param pbuf        Pointer to buffer
714  * \param buf_size    Size of buffer
715  *
716  * \return Status of procedure
717  * \retval STATUS_OK Job started successfully
718  * \retval STATUS_ERR_DENIED Endpoint is not ready
719  */
720 enum status_code usb_device_endpoint_write_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
721         uint8_t* pbuf, uint32_t buf_size)
722 {
723     /* Sanity check arguments */
724     Assert(module_inst);
725     Assert(module_inst->hw);
726     Assert(ep_num < USB_EPT_NUM);
727
728     uint8_t flag;
729     flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE1);
730     if ((enum usb_device_endpoint_type)(flag) == USB_DEVICE_ENDPOINT_TYPE_DISABLE) {
731         return STATUS_ERR_DENIED;
732     };
733
734     /* get endpoint configuration from setting register */
735     usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].ADDR.reg = (uint32_t)pbuf;
736     usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
737     usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = buf_size;
738     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
739
740     return STATUS_OK;
741 }
742
743 /**
744  * \brief Start read buffer job on a endpoint
745  *
746  * \param module_inst Pointer to USB module instance
747  * \param ep_num      Endpoint number
748  * \param pbuf        Pointer to buffer
749  * \param buf_size    Size of buffer
750  *
751  * \return Status of procedure
752  * \retval STATUS_OK Job started successfully
753  * \retval STATUS_ERR_DENIED Endpoint is not ready
754  */
755 enum status_code usb_device_endpoint_read_buffer_job(struct usb_module *module_inst,uint8_t ep_num,
756         uint8_t* pbuf, uint32_t buf_size)
757 {
758     /* Sanity check arguments */
759     Assert(module_inst);
760     Assert(module_inst->hw);
761     Assert(ep_num < USB_EPT_NUM);
762
763     uint8_t flag;
764     flag = (uint8_t)(module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPCFG.bit.EPTYPE0);
765     if ((enum usb_device_endpoint_type)(flag) == USB_DEVICE_ENDPOINT_TYPE_DISABLE) {
766         return STATUS_ERR_DENIED;
767     };
768
769     /* get endpoint configuration from setting register */
770     usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].ADDR.reg = (uint32_t)pbuf;
771     usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = buf_size;
772     usb_descriptor_table.usb_endpoint_table[ep_num].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
773     module_inst->hw->DEVICE.DeviceEndpoint[ep_num].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
774
775     return STATUS_OK;
776 }
777
778 /**
779  * \brief Start setup packet read job on a endpoint
780  *
781  * \param module_inst Pointer to USB device module instance
782  * \param pbuf        Pointer to buffer
783  *
784  * \return Status of procedure
785  * \retval STATUS_OK Job started successfully
786  * \retval STATUS_ERR_DENIED Endpoint is not ready
787  */
788 enum status_code usb_device_endpoint_setup_buffer_job(struct usb_module *module_inst,
789         uint8_t* pbuf)
790 {
791     /* Sanity check arguments */
792     Assert(module_inst);
793     Assert(module_inst->hw);
794
795     /* get endpoint configuration from setting register */
796     usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].ADDR.reg = (uint32_t)pbuf;
797     usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 8;
798     usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
799     module_inst->hw->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
800
801     return STATUS_OK;
802 }
803
804 static void _usb_device_interrupt_handler(void)
805 {
806     uint16_t ep_inst;
807     uint16_t flags, flags_run;
808     ep_inst = _usb_instances->hw->DEVICE.EPINTSMRY.reg;
809
810     /* device interrupt */
811     if (0 == ep_inst) {
812         int i;
813
814         /* get interrupt flags */
815         flags = _usb_instances->hw->DEVICE.INTFLAG.reg;
816         flags_run = flags &
817                 _usb_instances->device_enabled_callback_mask &
818                 _usb_instances->device_registered_callback_mask;
819
820         for (i = 0; i < USB_DEVICE_CALLBACK_N; i ++) {
821             if (flags & _usb_device_irq_bits[i]) {
822                 _usb_instances->hw->DEVICE.INTFLAG.reg =
823                         _usb_device_irq_bits[i];
824             }
825             if (flags_run & _usb_device_irq_bits[i]) {
826                 if (i == USB_DEVICE_CALLBACK_LPMSUSP) {
827                     device_callback_lpm_wakeup_enable =
828                             usb_descriptor_table.usb_endpoint_table[0].DeviceDescBank[0].EXTREG.bit.VARIABLE
829                             & USB_LPM_ATTRIBUT_REMOTEWAKE_MASK;
830                 }
831                 (_usb_instances->device_callback[i])(_usb_instances, &device_callback_lpm_wakeup_enable);
832             }
833         }
834
835     } else {
836         /* endpoint interrupt */
837
838         for (uint8_t i = 0; i < USB_EPT_NUM; i++) {
839
840             if (ep_inst & (1 << i)) {
841                 flags = _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg;
842                 flags_run = flags &
843                         _usb_instances->device_endpoint_enabled_callback_mask[i] &
844                         _usb_instances->device_endpoint_registered_callback_mask[i];
845
846                 // endpoint transfer stall interrupt
847                 if (flags & USB_DEVICE_EPINTFLAG_STALL_Msk) {
848                     if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL1) {
849                         _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL1;
850                         ep_callback_para.endpoint_address = USB_EP_DIR_IN | i;
851                     } else if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_STALL0) {
852                         _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL0;
853                         ep_callback_para.endpoint_address = USB_EP_DIR_OUT | i;
854                     }
855
856                     if (flags_run & USB_DEVICE_EPINTFLAG_STALL_Msk) {
857                         (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_STALL])(_usb_instances,&ep_callback_para);
858                     }
859                     return;
860                 }
861
862                 // endpoint received setup interrupt
863                 if (flags & USB_DEVICE_EPINTFLAG_RXSTP) {
864                     _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP;
865                     if(_usb_instances->device_endpoint_enabled_callback_mask[i] & _usb_endpoint_irq_bits[USB_DEVICE_ENDPOINT_CALLBACK_RXSTP]) {
866                         ep_callback_para.received_bytes = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT);
867                         (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_RXSTP])(_usb_instances,&ep_callback_para);
868                     }
869                     return;
870                 }
871
872                 // endpoint transfer complete interrupt
873                 if (flags & USB_DEVICE_EPINTFLAG_TRCPT_Msk) {
874                     if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT1) {
875                         _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
876                         ep_callback_para.endpoint_address = USB_EP_DIR_IN | i;
877                         ep_callback_para.sent_bytes = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT);
878
879                     } else if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0) {
880                         _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
881                         ep_callback_para.endpoint_address = USB_EP_DIR_OUT | i;
882                         ep_callback_para.received_bytes = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT);
883                         ep_callback_para.out_buffer_size = (uint16_t)(usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE);
884                     }
885                     if(flags_run & USB_DEVICE_EPINTFLAG_TRCPT_Msk) {
886                         (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_TRCPT])(_usb_instances,&ep_callback_para);
887                     }
888                     return;
889                 }
890
891                 // endpoint transfer fail interrupt
892                 if (flags & USB_DEVICE_EPINTFLAG_TRFAIL_Msk) {
893                     if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRFAIL1) {
894                         _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRFAIL1;
895                         if (usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[1].STATUS_BK.reg & USB_DEVICE_STATUS_BK_ERRORFLOW) {
896                             usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[1].STATUS_BK.reg &= ~USB_DEVICE_STATUS_BK_ERRORFLOW;
897                         }
898                         ep_callback_para.endpoint_address = USB_EP_DIR_IN | i;
899                         if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT1) {
900                             return;
901                         }
902                     } else if(_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRFAIL0) {
903                         _usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRFAIL0;
904                         if (usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].STATUS_BK.reg & USB_DEVICE_STATUS_BK_ERRORFLOW) {
905                             usb_descriptor_table.usb_endpoint_table[i].DeviceDescBank[0].STATUS_BK.reg &= ~USB_DEVICE_STATUS_BK_ERRORFLOW;
906                         }
907                         ep_callback_para.endpoint_address = USB_EP_DIR_OUT | i;
908                         if (_usb_instances->hw->DEVICE.DeviceEndpoint[i].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0) {
909                             return;
910                         }
911                     }
912
913                     if(flags_run & USB_DEVICE_EPINTFLAG_TRFAIL_Msk) {
914                         (_usb_instances->device_endpoint_callback[i][USB_DEVICE_ENDPOINT_CALLBACK_TRFAIL])(_usb_instances,&ep_callback_para);
915                     }
916                     return;
917                 }
918             }
919         }
920     }
921 }
922
923 /**
924  * \brief Enable the USB module peripheral
925  *
926  * \param module_inst pointer to USB module instance
927  */
928 void usb_enable(struct usb_module *module_inst)
929 {
930     Assert(module_inst);
931     Assert(module_inst->hw);
932
933     module_inst->hw->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE;
934     while (module_inst->hw->DEVICE.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
935 }
936
937 /**
938  * \brief Disable the USB module peripheral
939  *
940  * \param module_inst pointer to USB module instance
941  */
942 void usb_disable(struct usb_module *module_inst)
943 {
944     Assert(module_inst);
945     Assert(module_inst->hw);
946
947     module_inst->hw->DEVICE.INTENCLR.reg = USB_DEVICE_INTENCLR_MASK;
948     module_inst->hw->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_MASK;
949     module_inst->hw->DEVICE.CTRLA.reg &= ~USB_CTRLA_ENABLE;
950     while (module_inst->hw->DEVICE.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
951 }
952
953 /**
954  * \brief Interrupt handler for the USB module.
955  */
956 void USB_0_Handler(void)
957 {
958     if (_usb_instances->hw->DEVICE.CTRLA.bit.MODE) {
959
960     } else {
961         /*device mode ISR */
962         _usb_device_interrupt_handler();
963     }
964 }
965
966 void USB_1_Handler(void)
967 {
968     _usb_device_interrupt_handler();
969 }
970
971 void USB_2_Handler(void)
972 {
973     _usb_device_interrupt_handler();
974 }
975
976 void USB_3_Handler(void)
977 {
978     _usb_device_interrupt_handler();
979 }
980
981 /**
982  * \brief Get the default USB module settings
983  *
984  * \param[out] module_config  Configuration structure to initialize to default values
985  */
986 void usb_get_config_defaults(struct usb_config *module_config)
987 {
988     Assert(module_config);
989
990     /* Sanity check arguments */
991     Assert(module_config);
992     /* Write default configuration to config struct */
993     module_config->select_host_mode = 0;
994     module_config->run_in_standby = 1;
995     module_config->source_generator = 0;
996     module_config->speed_mode = USB_SPEED_FULL;
997 }
998
999 #define NVM_USB_PAD_TRANSN_POS  45
1000 #define NVM_USB_PAD_TRANSN_SIZE 5
1001 #define NVM_USB_PAD_TRANSP_POS  50
1002 #define NVM_USB_PAD_TRANSP_SIZE 5
1003 #define NVM_USB_PAD_TRIM_POS  55
1004 #define NVM_USB_PAD_TRIM_SIZE 3
1005
1006 /**
1007  * \brief Initializes USB module instance
1008  *
1009  * Enables the clock and initializes the USB module, based on the given
1010  * configuration values.
1011  *
1012  * \param[in,out] module_inst   Pointer to the software module instance struct
1013  * \param[in]     hw            Pointer to the USB hardware module
1014  * \param[in]     module_config Pointer to the USB configuration options struct
1015  *
1016  * \return Status of the initialization procedure.
1017  *
1018  * \retval STATUS_OK           The module was initialized successfully
1019  */
1020
1021 #define GCLK_USB 10
1022
1023 enum status_code usb_init(struct usb_module *module_inst, Usb *const hw,
1024         struct usb_config *module_config)
1025 {
1026     /* Sanity check arguments */
1027     Assert(hw);
1028     Assert(module_inst);
1029     Assert(module_config);
1030
1031     uint32_t i,j;
1032     uint32_t pad_transn, pad_transp, pad_trim;
1033
1034     Gclk *pgclk = GCLK;
1035     Mclk *pmclk = MCLK;
1036     Port *pport = PORT;
1037     Oscctrl *posc = OSCCTRL;
1038
1039     _usb_instances = module_inst;
1040
1041     /* Associate the software module instance with the hardware module */
1042     module_inst->hw = hw;
1043
1044     //setup peripheral and synchronous bus clocks to USB
1045     pmclk->AHBMASK.bit.USB_ = 1;
1046     pmclk->APBBMASK.bit.USB_ = 1;
1047
1048     /* Set up the USB DP/DN pins */
1049     pport->Group[0].PMUX[12].reg = 0x77; //PA24, PA25, function column H for USB D-, D+
1050     pport->Group[0].PINCFG[24].bit.PMUXEN = 1;
1051     pport->Group[0].PINCFG[25].bit.PMUXEN = 1;
1052     pport->Group[1].PMUX[11].bit.PMUXE = 7; //PB22, function column H for USB SOF_1KHz output
1053     pport->Group[1].PINCFG[22].bit.PMUXEN = 1;
1054
1055     //configure and enable DFLL for USB clock recovery mode at 48MHz
1056     posc->DFLLCTRLA.bit.ENABLE = 0;
1057     while (posc->DFLLSYNC.bit.ENABLE);
1058     while (posc->DFLLSYNC.bit.DFLLCTRLB);
1059     posc->DFLLCTRLB.bit.USBCRM = 1;
1060     while (posc->DFLLSYNC.bit.DFLLCTRLB);
1061     posc->DFLLCTRLB.bit.MODE = 1;
1062     while (posc->DFLLSYNC.bit.DFLLCTRLB);
1063     posc->DFLLCTRLB.bit.QLDIS = 0;
1064     while (posc->DFLLSYNC.bit.DFLLCTRLB);
1065     posc->DFLLCTRLB.bit.CCDIS = 1;
1066     posc->DFLLMUL.bit.MUL = 0xbb80;   //4800 x 1KHz
1067     while (posc->DFLLSYNC.bit.DFLLMUL);
1068     posc->DFLLCTRLA.bit.ENABLE = 1;
1069     while (posc->DFLLSYNC.bit.ENABLE);
1070
1071     /* Setup clock for module */
1072     pgclk->PCHCTRL[GCLK_USB].bit.GEN = 0;
1073     pgclk->PCHCTRL[GCLK_USB].bit.CHEN = 1;
1074
1075     /* Reset */
1076     hw->DEVICE.CTRLA.bit.SWRST = 1;
1077     while (hw->DEVICE.SYNCBUSY.bit.SWRST) {
1078         /* Sync wait */
1079     }
1080
1081     /* Change QOS values to have the best performance and correct USB behaviour */
1082     USB->DEVICE.QOSCTRL.bit.CQOS = 2;
1083     USB->DEVICE.QOSCTRL.bit.DQOS = 2;
1084
1085     /* Load Pad Calibration */
1086
1087     pad_transn = (USB_FUSES_TRANSN_ADDR >>  USB_FUSES_TRANSN_Pos) & USB_FUSES_TRANSN_Msk;
1088     if (pad_transn == 0x1F) {
1089         pad_transn = 5;
1090     }
1091
1092     hw->DEVICE.PADCAL.bit.TRANSN = pad_transn;
1093
1094     pad_transp = (USB_FUSES_TRANSP_ADDR >>  USB_FUSES_TRANSP_Pos) & USB_FUSES_TRANSP_Msk;
1095     if (pad_transp == 0x1F) {
1096         pad_transp = 29;
1097     }
1098
1099     hw->DEVICE.PADCAL.bit.TRANSP = pad_transp;
1100
1101     pad_trim = (USB_FUSES_TRIM_ADDR >>  USB_FUSES_TRIM_Pos) & USB_FUSES_TRIM_Msk;
1102     if (pad_trim == 0x07) {
1103         pad_trim = 3;
1104     }
1105
1106     hw->DEVICE.PADCAL.bit.TRIM = pad_trim;
1107
1108     /* Set the configuration */
1109     hw->DEVICE.CTRLA.bit.MODE = module_config->select_host_mode;
1110     hw->DEVICE.CTRLA.bit.RUNSTDBY = module_config->run_in_standby;
1111     hw->DEVICE.DESCADD.reg = (uint32_t)(&usb_descriptor_table.usb_endpoint_table[0]);
1112     if (USB_SPEED_FULL == module_config->speed_mode) {
1113         module_inst->hw->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val;
1114     } else if(USB_SPEED_LOW == module_config->speed_mode) {
1115         module_inst->hw->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_LS_Val;
1116     }
1117
1118     memset((uint8_t *)(&usb_descriptor_table.usb_endpoint_table[0]), 0,
1119             sizeof(usb_descriptor_table.usb_endpoint_table));
1120
1121     /*  device callback related */
1122     for (i = 0; i < USB_DEVICE_CALLBACK_N; i++) {
1123         module_inst->device_callback[i] = NULL;
1124     }
1125     for (i = 0; i < USB_EPT_NUM; i++) {
1126         for(j = 0; j < USB_DEVICE_EP_CALLBACK_N; j++) {
1127             module_inst->device_endpoint_callback[i][j] = NULL;
1128         }
1129     }
1130     module_inst->device_registered_callback_mask = 0;
1131     module_inst->device_enabled_callback_mask = 0;
1132     for (j = 0; j < USB_EPT_NUM; j++) {
1133         module_inst->device_endpoint_registered_callback_mask[j] = 0;
1134         module_inst->device_endpoint_enabled_callback_mask[j] = 0;
1135     }
1136
1137     /* Enable interrupts for this USB module */
1138     NVIC_EnableIRQ(USB_0_IRQn);
1139     NVIC_EnableIRQ(USB_2_IRQn);
1140     NVIC_EnableIRQ(USB_3_IRQn);
1141
1142     return STATUS_OK;
1143 }
1144