1 /*!
2 \file drv_usb_dev.h
3 \brief USB device low level driver header file
4
5 \version 2020-08-04, V1.1.0, firmware for GD32VF103
6 \version 2020-12-11, V1.1.1, firmware for GD32VF103
7 */
8
9 /*
10 Copyright (c) 2020, GigaDevice Semiconductor Inc.
11
12 Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14
15 1. Redistributions of source code must retain the above copyright notice, this
16 list of conditions and the following disclaimer.
17 2. Redistributions in binary form must reproduce the above copyright notice,
18 this list of conditions and the following disclaimer in the documentation
19 and/or other materials provided with the distribution.
20 3. Neither the name of the copyright holder nor the names of its contributors
21 may be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGE.
34 */
35
36 #ifndef __DRV_USB_DEV_H
37 #define __DRV_USB_DEV_H
38
39 #include "usbd_conf.h"
40 #include "drv_usb_core.h"
41
42 enum usb_ctl_status {
43 USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */
44 USB_CTL_DATA_IN, /*!< USB control transfer data in state */
45 USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */
46 USB_CTL_DATA_OUT, /*!< USB control transfer data out state */
47 USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */
48 USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/
49 USB_CTL_STATUS_OUT /*!< USB control transfer status out state */
50 };
51
52 #define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */
53 #define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */
54
55 /* USB descriptor */
56 typedef struct _usb_desc {
57 uint8_t *dev_desc; /*!< device descriptor */
58 uint8_t *config_desc; /*!< configure descriptor */
59 uint8_t *bos_desc; /*!< BOS descriptor */
60
61 void* const *strings; /*!< string descriptor */
62 } usb_desc;
63
64 /* USB power management */
65 typedef struct _usb_pm {
66 uint8_t power_mode; /*!< power mode */
67 uint8_t power_low; /*!< power low */
68 uint8_t dev_remote_wakeup; /*!< remote wakeup */
69 uint8_t remote_wakeup_on; /*!< remote wakeup on */
70 } usb_pm;
71
72 /* USB control information */
73 typedef struct _usb_control {
74 usb_req req; /*!< USB standard device request */
75
76 uint8_t ctl_state; /*!< USB control transfer state */
77 uint8_t ctl_zlp; /*!< zero length package */
78 } usb_control;
79
80 typedef struct
81 {
82 struct {
83 uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */
84 uint8_t pad: 3; /*!< padding between number and direction */
85 uint8_t dir: 1; /*!< the endpoint direction */
86 } ep_addr;
87
88 uint8_t ep_type; /*!< USB endpoint type */
89 uint8_t ep_stall; /*!< USB endpoint stall status */
90
91 uint8_t frame_num; /*!< number of frame */
92 uint16_t max_len; /*!< Maximum packet length */
93
94 /* transaction level variables */
95 uint8_t *xfer_buf; /*!< transmit buffer */
96 uint32_t xfer_len; /*!< transmit buffer length */
97 uint32_t xfer_count; /*!< transmit buffer count */
98
99 uint32_t remain_len; /*!< remain packet length */
100
101 uint32_t dma_addr; /*!< DMA address */
102 } usb_transc;
103
104 typedef struct _usb_core_driver usb_dev;
105
106 typedef struct _usb_class_core
107 {
108 uint8_t command; /*!< device class request command */
109 uint8_t alter_set; /*!< alternative set */
110
111 uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */
112 uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< de-initialize handler */
113
114 uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */
115
116 uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */
117
118 uint8_t (*ctlx_in) (usb_dev *udev); /*!< device contrl in callback */
119 uint8_t (*ctlx_out) (usb_dev *udev); /*!< device contrl out callback */
120
121 uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */
122 uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */
123
124 uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */
125
126 uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */
127 uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */
128 } usb_class_core;
129
130 typedef struct _usb_perp_dev
131 {
132 uint8_t config; /*!< configuration */
133 uint8_t dev_addr; /*!< device address */
134
135 __IO uint8_t cur_status; /*!< current status */
136 __IO uint8_t backup_status; /*!< backup status */
137
138 usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */
139 usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */
140
141 usb_pm pm; /*!< power management */
142 usb_control control; /*!< USB control information */
143 usb_desc *desc; /*!< USB descriptors pointer */
144 usb_class_core *class_core; /*!< class driver */
145 void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */
146 void *user_data; /*!< user data pointer */
147 void *pdata; /*!< reserved data pointer */
148 } usb_perp_dev;
149
150 typedef struct _usb_core_driver
151 {
152 usb_core_basic bp; /*!< USB basic parameters */
153 usb_core_regs regs; /*!< USB registers */
154 usb_perp_dev dev; /*!< USB peripheral device */
155 } usb_core_driver;
156
157 /* static inline function definitions */
158
159 /*!
160 \brief configure the USB device to be disconnected
161 \param[in] udev: pointer to USB device
162 \param[out] none
163 \retval operation status
164 */
usb_dev_disconnect(usb_core_driver * udev)165 static inline void usb_dev_disconnect (usb_core_driver *udev)
166 {
167 udev->regs.dr->DCTL |= DCTL_SD;
168 }
169
170 /*!
171 \brief configure the USB device to be connected
172 \param[in] udev: pointer to USB device
173 \param[out] none
174 \retval operation status
175 */
usb_dev_connect(usb_core_driver * udev)176 static inline void usb_dev_connect (usb_core_driver *udev)
177 {
178 udev->regs.dr->DCTL &= ~DCTL_SD;
179 }
180
181 /*!
182 \brief set the USB device address
183 \param[in] udev: pointer to USB device
184 \param[in] dev_addr: device address for setting
185 \param[out] none
186 \retval operation status
187 */
usb_devaddr_set(usb_core_driver * udev,uint8_t dev_addr)188 static inline void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr)
189 {
190 udev->regs.dr->DCFG &= ~DCFG_DAR;
191 udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4;
192 }
193
194 /*!
195 \brief read device all OUT endpoint interrupt register
196 \param[in] udev: pointer to USB device
197 \param[out] none
198 \retval interrupt status
199 */
usb_oepintnum_read(usb_core_driver * udev)200 static inline uint32_t usb_oepintnum_read (usb_core_driver *udev)
201 {
202 uint32_t value = udev->regs.dr->DAEPINT;
203
204 value &= udev->regs.dr->DAEPINTEN;
205
206 return (value & DAEPINT_OEPITB) >> 16;
207 }
208
209 /*!
210 \brief read device OUT endpoint interrupt flag register
211 \param[in] udev: pointer to USB device
212 \param[in] ep_num: endpoint number
213 \param[out] none
214 \retval interrupt status
215 */
usb_oepintr_read(usb_core_driver * udev,uint8_t ep_num)216 static inline uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num)
217 {
218 uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF;
219
220 value &= udev->regs.dr->DOEPINTEN;
221
222 return value;
223 }
224
225 /*!
226 \brief read device all IN endpoint interrupt register
227 \param[in] udev: pointer to USB device
228 \param[out] none
229 \retval interrupt status
230 */
usb_iepintnum_read(usb_core_driver * udev)231 static inline uint32_t usb_iepintnum_read (usb_core_driver *udev)
232 {
233 uint32_t value = udev->regs.dr->DAEPINT;
234
235 value &= udev->regs.dr->DAEPINTEN;
236
237 return value & DAEPINT_IEPITB;
238 }
239
240 /*!
241 \brief set remote wakeup signaling
242 \param[in] udev: pointer to USB device
243 \param[out] none
244 \retval none
245 */
usb_rwkup_set(usb_core_driver * udev)246 static inline void usb_rwkup_set (usb_core_driver *udev)
247 {
248 if (udev->dev.pm.dev_remote_wakeup) {
249 /* enable remote wakeup signaling */
250 udev->regs.dr->DCTL |= DCTL_RWKUP;
251 }
252 }
253
254 /*!
255 \brief reset remote wakeup signaling
256 \param[in] udev: pointer to USB device
257 \param[out] none
258 \retval none
259 */
usb_rwkup_reset(usb_core_driver * udev)260 static inline void usb_rwkup_reset (usb_core_driver *udev)
261 {
262 if (udev->dev.pm.dev_remote_wakeup) {
263 /* disable remote wakeup signaling */
264 udev->regs.dr->DCTL &= ~DCTL_RWKUP;
265 }
266 }
267
268 /* function declarations */
269 /* initialize USB core registers for device mode */
270 usb_status usb_devcore_init (usb_core_driver *udev);
271 /* enable the USB device mode interrupts */
272 usb_status usb_devint_enable (usb_core_driver *udev);
273 /* active the USB endpoint 0 transaction */
274 usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc);
275 /* active the USB transaction */
276 usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc);
277 /* deactivate the USB transaction */
278 usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc);
279 /* configure USB transaction to start IN transfer */
280 usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc);
281 /* configure USB transaction to start OUT transfer */
282 usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc);
283 /* set the USB transaction STALL status */
284 usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc);
285 /* clear the USB transaction STALL status */
286 usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc);
287 /* read device IN endpoint interrupt flag register */
288 uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num);
289 /* configures OUT endpoint 0 to receive SETUP packets */
290 void usb_ctlep_startout (usb_core_driver *udev);
291 /* active remote wakeup signaling */
292 void usb_rwkup_active (usb_core_driver *udev);
293 /* active USB core clock */
294 void usb_clock_active (usb_core_driver *udev);
295 /* USB device suspend */
296 void usb_dev_suspend (usb_core_driver *udev);
297 /* stop the device and clean up FIFOs */
298 void usb_dev_stop (usb_core_driver *udev);
299
300 #endif /* __DRV_USB_DEV_H */
301