xref: /arm-trusted-firmware/drivers/usb/usb_device.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <stdint.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <common/debug.h>
11*91f16700Schasinglulu #include <drivers/usb_device.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu /* Define for EP address */
14*91f16700Schasinglulu #define EP_DIR_MASK		BIT(7)
15*91f16700Schasinglulu #define EP_DIR_IN		BIT(7)
16*91f16700Schasinglulu #define EP_NUM_MASK		GENMASK(3, 0)
17*91f16700Schasinglulu 
18*91f16700Schasinglulu #define EP0_IN			(0U | EP_DIR_IN)
19*91f16700Schasinglulu #define EP0_OUT			0U
20*91f16700Schasinglulu 
21*91f16700Schasinglulu /* USB address between 1 through 127 = 0x7F mask */
22*91f16700Schasinglulu #define ADDRESS_MASK		GENMASK(6, 0)
23*91f16700Schasinglulu 
24*91f16700Schasinglulu /*
25*91f16700Schasinglulu  * Set a STALL condition over an endpoint
26*91f16700Schasinglulu  * pdev: USB handle
27*91f16700Schasinglulu  * ep_addr: endpoint address
28*91f16700Schasinglulu  * return : status
29*91f16700Schasinglulu  */
30*91f16700Schasinglulu static enum usb_status usb_core_set_stall(struct usb_handle *pdev, uint8_t ep_addr)
31*91f16700Schasinglulu {
32*91f16700Schasinglulu 	struct usbd_ep *ep;
33*91f16700Schasinglulu 	struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
34*91f16700Schasinglulu 	uint8_t num;
35*91f16700Schasinglulu 
36*91f16700Schasinglulu 	num = ep_addr & EP_NUM_MASK;
37*91f16700Schasinglulu 	if (num >= USBD_EP_NB) {
38*91f16700Schasinglulu 		return USBD_FAIL;
39*91f16700Schasinglulu 	}
40*91f16700Schasinglulu 	if ((EP_DIR_MASK & ep_addr) == EP_DIR_IN) {
41*91f16700Schasinglulu 		ep = &hpcd->in_ep[num];
42*91f16700Schasinglulu 		ep->is_in = true;
43*91f16700Schasinglulu 	} else {
44*91f16700Schasinglulu 		ep = &hpcd->out_ep[num];
45*91f16700Schasinglulu 		ep->is_in = false;
46*91f16700Schasinglulu 	}
47*91f16700Schasinglulu 	ep->num = num;
48*91f16700Schasinglulu 
49*91f16700Schasinglulu 	pdev->driver->ep_set_stall(hpcd->instance, ep);
50*91f16700Schasinglulu 	if (num == 0U) {
51*91f16700Schasinglulu 		pdev->driver->ep0_out_start(hpcd->instance);
52*91f16700Schasinglulu 	}
53*91f16700Schasinglulu 
54*91f16700Schasinglulu 	return USBD_OK;
55*91f16700Schasinglulu }
56*91f16700Schasinglulu 
57*91f16700Schasinglulu /*
58*91f16700Schasinglulu  * usb_core_get_desc
59*91f16700Schasinglulu  *         Handle Get Descriptor requests
60*91f16700Schasinglulu  * pdev : device instance
61*91f16700Schasinglulu  * req : usb request
62*91f16700Schasinglulu  */
63*91f16700Schasinglulu static void usb_core_get_desc(struct usb_handle *pdev, struct usb_setup_req *req)
64*91f16700Schasinglulu {
65*91f16700Schasinglulu 	uint16_t len;
66*91f16700Schasinglulu 	uint8_t *pbuf;
67*91f16700Schasinglulu 	uint8_t desc_type = HIBYTE(req->value);
68*91f16700Schasinglulu 	uint8_t desc_idx = LOBYTE(req->value);
69*91f16700Schasinglulu 
70*91f16700Schasinglulu 	switch (desc_type) {
71*91f16700Schasinglulu 	case USB_DESC_TYPE_DEVICE:
72*91f16700Schasinglulu 		pbuf = pdev->desc->get_device_desc(&len);
73*91f16700Schasinglulu 		break;
74*91f16700Schasinglulu 
75*91f16700Schasinglulu 	case USB_DESC_TYPE_CONFIGURATION:
76*91f16700Schasinglulu 		pbuf = pdev->desc->get_config_desc(&len);
77*91f16700Schasinglulu 		break;
78*91f16700Schasinglulu 
79*91f16700Schasinglulu 	case USB_DESC_TYPE_STRING:
80*91f16700Schasinglulu 		switch (desc_idx) {
81*91f16700Schasinglulu 		case USBD_IDX_LANGID_STR:
82*91f16700Schasinglulu 			pbuf = pdev->desc->get_lang_id_desc(&len);
83*91f16700Schasinglulu 			break;
84*91f16700Schasinglulu 
85*91f16700Schasinglulu 		case USBD_IDX_MFC_STR:
86*91f16700Schasinglulu 			pbuf = pdev->desc->get_manufacturer_desc(&len);
87*91f16700Schasinglulu 			break;
88*91f16700Schasinglulu 
89*91f16700Schasinglulu 		case USBD_IDX_PRODUCT_STR:
90*91f16700Schasinglulu 			pbuf = pdev->desc->get_product_desc(&len);
91*91f16700Schasinglulu 			break;
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 		case USBD_IDX_SERIAL_STR:
94*91f16700Schasinglulu 			pbuf = pdev->desc->get_serial_desc(&len);
95*91f16700Schasinglulu 			break;
96*91f16700Schasinglulu 
97*91f16700Schasinglulu 		case USBD_IDX_CONFIG_STR:
98*91f16700Schasinglulu 			pbuf = pdev->desc->get_configuration_desc(&len);
99*91f16700Schasinglulu 			break;
100*91f16700Schasinglulu 
101*91f16700Schasinglulu 		case USBD_IDX_INTERFACE_STR:
102*91f16700Schasinglulu 			pbuf = pdev->desc->get_interface_desc(&len);
103*91f16700Schasinglulu 			break;
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 		/* For all USER string */
106*91f16700Schasinglulu 		case USBD_IDX_USER0_STR:
107*91f16700Schasinglulu 		default:
108*91f16700Schasinglulu 			pbuf = pdev->desc->get_usr_desc(desc_idx - USBD_IDX_USER0_STR, &len);
109*91f16700Schasinglulu 			break;
110*91f16700Schasinglulu 		}
111*91f16700Schasinglulu 		break;
112*91f16700Schasinglulu 
113*91f16700Schasinglulu 	case USB_DESC_TYPE_DEVICE_QUALIFIER:
114*91f16700Schasinglulu 		pbuf = pdev->desc->get_device_qualifier_desc(&len);
115*91f16700Schasinglulu 		break;
116*91f16700Schasinglulu 
117*91f16700Schasinglulu 	case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
118*91f16700Schasinglulu 		if (pdev->desc->get_other_speed_config_desc == NULL) {
119*91f16700Schasinglulu 			usb_core_ctl_error(pdev);
120*91f16700Schasinglulu 			return;
121*91f16700Schasinglulu 		}
122*91f16700Schasinglulu 		pbuf = pdev->desc->get_other_speed_config_desc(&len);
123*91f16700Schasinglulu 		break;
124*91f16700Schasinglulu 
125*91f16700Schasinglulu 	default:
126*91f16700Schasinglulu 		ERROR("Unknown request %i\n", desc_type);
127*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
128*91f16700Schasinglulu 		return;
129*91f16700Schasinglulu 	}
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	if ((len != 0U) && (req->length != 0U)) {
132*91f16700Schasinglulu 		len = MIN(len, req->length);
133*91f16700Schasinglulu 
134*91f16700Schasinglulu 		/* Start the transfer */
135*91f16700Schasinglulu 		usb_core_transmit_ep0(pdev, pbuf, len);
136*91f16700Schasinglulu 	}
137*91f16700Schasinglulu }
138*91f16700Schasinglulu 
139*91f16700Schasinglulu /*
140*91f16700Schasinglulu  * usb_core_set_config
141*91f16700Schasinglulu  *         Handle Set device configuration request
142*91f16700Schasinglulu  * pdev : device instance
143*91f16700Schasinglulu  * req : usb request
144*91f16700Schasinglulu  */
145*91f16700Schasinglulu static void usb_core_set_config(struct usb_handle *pdev, struct usb_setup_req *req)
146*91f16700Schasinglulu {
147*91f16700Schasinglulu 	static uint8_t cfgidx;
148*91f16700Schasinglulu 
149*91f16700Schasinglulu 	cfgidx = LOBYTE(req->value);
150*91f16700Schasinglulu 
151*91f16700Schasinglulu 	if (cfgidx > USBD_MAX_NUM_CONFIGURATION) {
152*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
153*91f16700Schasinglulu 		return;
154*91f16700Schasinglulu 	}
155*91f16700Schasinglulu 
156*91f16700Schasinglulu 	switch (pdev->dev_state) {
157*91f16700Schasinglulu 	case USBD_STATE_ADDRESSED:
158*91f16700Schasinglulu 		if (cfgidx != 0U) {
159*91f16700Schasinglulu 			pdev->dev_config = cfgidx;
160*91f16700Schasinglulu 			pdev->dev_state = USBD_STATE_CONFIGURED;
161*91f16700Schasinglulu 			if (!pdev->class) {
162*91f16700Schasinglulu 				usb_core_ctl_error(pdev);
163*91f16700Schasinglulu 				return;
164*91f16700Schasinglulu 			}
165*91f16700Schasinglulu 			/* Set configuration and Start the Class */
166*91f16700Schasinglulu 			if (pdev->class->init(pdev, cfgidx) != 0U) {
167*91f16700Schasinglulu 				usb_core_ctl_error(pdev);
168*91f16700Schasinglulu 				return;
169*91f16700Schasinglulu 			}
170*91f16700Schasinglulu 		}
171*91f16700Schasinglulu 		break;
172*91f16700Schasinglulu 
173*91f16700Schasinglulu 	case USBD_STATE_CONFIGURED:
174*91f16700Schasinglulu 		if (cfgidx == 0U) {
175*91f16700Schasinglulu 			pdev->dev_state = USBD_STATE_ADDRESSED;
176*91f16700Schasinglulu 			pdev->dev_config = cfgidx;
177*91f16700Schasinglulu 			pdev->class->de_init(pdev, cfgidx);
178*91f16700Schasinglulu 		} else if (cfgidx != pdev->dev_config) {
179*91f16700Schasinglulu 			if (pdev->class == NULL) {
180*91f16700Schasinglulu 				usb_core_ctl_error(pdev);
181*91f16700Schasinglulu 				return;
182*91f16700Schasinglulu 			}
183*91f16700Schasinglulu 			/* Clear old configuration */
184*91f16700Schasinglulu 			pdev->class->de_init(pdev, pdev->dev_config);
185*91f16700Schasinglulu 			/* Set new configuration */
186*91f16700Schasinglulu 			pdev->dev_config = cfgidx;
187*91f16700Schasinglulu 			/* Set configuration and start the USB class */
188*91f16700Schasinglulu 			if (pdev->class->init(pdev, cfgidx) != 0U) {
189*91f16700Schasinglulu 				usb_core_ctl_error(pdev);
190*91f16700Schasinglulu 				return;
191*91f16700Schasinglulu 			}
192*91f16700Schasinglulu 		}
193*91f16700Schasinglulu 		break;
194*91f16700Schasinglulu 
195*91f16700Schasinglulu 	default:
196*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
197*91f16700Schasinglulu 		return;
198*91f16700Schasinglulu 	}
199*91f16700Schasinglulu 
200*91f16700Schasinglulu 	/* Send status */
201*91f16700Schasinglulu 	usb_core_transmit_ep0(pdev, NULL, 0U);
202*91f16700Schasinglulu }
203*91f16700Schasinglulu 
204*91f16700Schasinglulu /*
205*91f16700Schasinglulu  * usb_core_get_status
206*91f16700Schasinglulu  *         Handle Get Status request
207*91f16700Schasinglulu  * pdev : device instance
208*91f16700Schasinglulu  * req : usb request
209*91f16700Schasinglulu  */
210*91f16700Schasinglulu static void usb_core_get_status(struct usb_handle *pdev,
211*91f16700Schasinglulu 				struct usb_setup_req *req)
212*91f16700Schasinglulu {
213*91f16700Schasinglulu 	if ((pdev->dev_state != USBD_STATE_ADDRESSED) &&
214*91f16700Schasinglulu 	    (pdev->dev_state != USBD_STATE_CONFIGURED)) {
215*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
216*91f16700Schasinglulu 		return;
217*91f16700Schasinglulu 	}
218*91f16700Schasinglulu 
219*91f16700Schasinglulu 	pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
220*91f16700Schasinglulu 
221*91f16700Schasinglulu 	if (pdev->dev_remote_wakeup != 0U) {
222*91f16700Schasinglulu 		pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
223*91f16700Schasinglulu 	}
224*91f16700Schasinglulu 
225*91f16700Schasinglulu 	/* Start the transfer */
226*91f16700Schasinglulu 	usb_core_transmit_ep0(pdev, (uint8_t *)&pdev->dev_config_status, 2U);
227*91f16700Schasinglulu }
228*91f16700Schasinglulu 
229*91f16700Schasinglulu /*
230*91f16700Schasinglulu  * usb_core_set_address
231*91f16700Schasinglulu  *         Set device address
232*91f16700Schasinglulu  * pdev : device instance
233*91f16700Schasinglulu  * req : usb request
234*91f16700Schasinglulu  */
235*91f16700Schasinglulu static void usb_core_set_address(struct usb_handle *pdev,
236*91f16700Schasinglulu 				 struct usb_setup_req *req)
237*91f16700Schasinglulu {
238*91f16700Schasinglulu 	uint8_t dev_addr;
239*91f16700Schasinglulu 
240*91f16700Schasinglulu 	if ((req->index != 0U) || (req->length != 0U)) {
241*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
242*91f16700Schasinglulu 		return;
243*91f16700Schasinglulu 	}
244*91f16700Schasinglulu 
245*91f16700Schasinglulu 	dev_addr = req->value & ADDRESS_MASK;
246*91f16700Schasinglulu 	if (pdev->dev_state != USBD_STATE_DEFAULT) {
247*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
248*91f16700Schasinglulu 		return;
249*91f16700Schasinglulu 	}
250*91f16700Schasinglulu 
251*91f16700Schasinglulu 	pdev->dev_address = dev_addr;
252*91f16700Schasinglulu 	pdev->driver->set_address(((struct pcd_handle *)(pdev->data))->instance, dev_addr);
253*91f16700Schasinglulu 
254*91f16700Schasinglulu 	/* Send status */
255*91f16700Schasinglulu 	usb_core_transmit_ep0(pdev, NULL, 0U);
256*91f16700Schasinglulu 
257*91f16700Schasinglulu 	if (dev_addr != 0U) {
258*91f16700Schasinglulu 		pdev->dev_state  = USBD_STATE_ADDRESSED;
259*91f16700Schasinglulu 	} else {
260*91f16700Schasinglulu 		pdev->dev_state  = USBD_STATE_DEFAULT;
261*91f16700Schasinglulu 	}
262*91f16700Schasinglulu }
263*91f16700Schasinglulu 
264*91f16700Schasinglulu /*
265*91f16700Schasinglulu  * usb_core_dev_req
266*91f16700Schasinglulu  *         Handle standard usb device requests
267*91f16700Schasinglulu  * pdev : device instance
268*91f16700Schasinglulu  * req : usb request
269*91f16700Schasinglulu  * return : status
270*91f16700Schasinglulu  */
271*91f16700Schasinglulu static enum usb_status usb_core_dev_req(struct usb_handle *pdev,
272*91f16700Schasinglulu 					struct usb_setup_req *req)
273*91f16700Schasinglulu {
274*91f16700Schasinglulu 	VERBOSE("receive request %i\n", req->b_request);
275*91f16700Schasinglulu 	switch (req->b_request) {
276*91f16700Schasinglulu 	case USB_REQ_GET_DESCRIPTOR:
277*91f16700Schasinglulu 		usb_core_get_desc(pdev, req);
278*91f16700Schasinglulu 		break;
279*91f16700Schasinglulu 
280*91f16700Schasinglulu 	case USB_REQ_SET_CONFIGURATION:
281*91f16700Schasinglulu 		usb_core_set_config(pdev, req);
282*91f16700Schasinglulu 		break;
283*91f16700Schasinglulu 
284*91f16700Schasinglulu 	case USB_REQ_GET_STATUS:
285*91f16700Schasinglulu 		usb_core_get_status(pdev, req);
286*91f16700Schasinglulu 		break;
287*91f16700Schasinglulu 
288*91f16700Schasinglulu 	case USB_REQ_SET_ADDRESS:
289*91f16700Schasinglulu 		usb_core_set_address(pdev, req);
290*91f16700Schasinglulu 		break;
291*91f16700Schasinglulu 
292*91f16700Schasinglulu 	case USB_REQ_GET_CONFIGURATION:
293*91f16700Schasinglulu 	case USB_REQ_SET_FEATURE:
294*91f16700Schasinglulu 	case USB_REQ_CLEAR_FEATURE:
295*91f16700Schasinglulu 	default:
296*91f16700Schasinglulu 		ERROR("NOT SUPPORTED %i\n", req->b_request);
297*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
298*91f16700Schasinglulu 		break;
299*91f16700Schasinglulu 	}
300*91f16700Schasinglulu 
301*91f16700Schasinglulu 	return USBD_OK;
302*91f16700Schasinglulu }
303*91f16700Schasinglulu 
304*91f16700Schasinglulu /*
305*91f16700Schasinglulu  * usb_core_itf_req
306*91f16700Schasinglulu  *         Handle standard usb interface requests
307*91f16700Schasinglulu  * pdev : device instance
308*91f16700Schasinglulu  * req : usb request
309*91f16700Schasinglulu  * return : status
310*91f16700Schasinglulu  */
311*91f16700Schasinglulu static enum usb_status usb_core_itf_req(struct usb_handle *pdev,
312*91f16700Schasinglulu 					struct usb_setup_req *req)
313*91f16700Schasinglulu {
314*91f16700Schasinglulu 	if (pdev->dev_state != USBD_STATE_CONFIGURED) {
315*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
316*91f16700Schasinglulu 		return USBD_OK;
317*91f16700Schasinglulu 	}
318*91f16700Schasinglulu 
319*91f16700Schasinglulu 	if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) {
320*91f16700Schasinglulu 		pdev->class->setup(pdev, req);
321*91f16700Schasinglulu 
322*91f16700Schasinglulu 		if (req->length == 0U) {
323*91f16700Schasinglulu 			usb_core_transmit_ep0(pdev, NULL, 0U);
324*91f16700Schasinglulu 		}
325*91f16700Schasinglulu 	} else {
326*91f16700Schasinglulu 		usb_core_ctl_error(pdev);
327*91f16700Schasinglulu 	}
328*91f16700Schasinglulu 
329*91f16700Schasinglulu 	return USBD_OK;
330*91f16700Schasinglulu }
331*91f16700Schasinglulu 
332*91f16700Schasinglulu /*
333*91f16700Schasinglulu  * usb_core_setup_stage
334*91f16700Schasinglulu  *         Handle the setup stage
335*91f16700Schasinglulu  * pdev: device instance
336*91f16700Schasinglulu  * psetup : setup buffer
337*91f16700Schasinglulu  * return : status
338*91f16700Schasinglulu  */
339*91f16700Schasinglulu static enum usb_status usb_core_setup_stage(struct usb_handle *pdev,
340*91f16700Schasinglulu 					    uint8_t *psetup)
341*91f16700Schasinglulu {
342*91f16700Schasinglulu 	struct usb_setup_req *req = &pdev->request;
343*91f16700Schasinglulu 
344*91f16700Schasinglulu 	/* Copy setup buffer into req structure */
345*91f16700Schasinglulu 	req->bm_request = psetup[0];
346*91f16700Schasinglulu 	req->b_request = psetup[1];
347*91f16700Schasinglulu 	req->value = psetup[2] + (psetup[3] << 8);
348*91f16700Schasinglulu 	req->index = psetup[4] + (psetup[5] << 8);
349*91f16700Schasinglulu 	req->length = psetup[6] + (psetup[7] << 8);
350*91f16700Schasinglulu 
351*91f16700Schasinglulu 	pdev->ep0_state = USBD_EP0_SETUP;
352*91f16700Schasinglulu 	pdev->ep0_data_len = pdev->request.length;
353*91f16700Schasinglulu 
354*91f16700Schasinglulu 	switch (pdev->request.bm_request & USB_REQ_RECIPIENT_MASK) {
355*91f16700Schasinglulu 	case USB_REQ_RECIPIENT_DEVICE:
356*91f16700Schasinglulu 		usb_core_dev_req(pdev, &pdev->request);
357*91f16700Schasinglulu 		break;
358*91f16700Schasinglulu 
359*91f16700Schasinglulu 	case USB_REQ_RECIPIENT_INTERFACE:
360*91f16700Schasinglulu 		usb_core_itf_req(pdev, &pdev->request);
361*91f16700Schasinglulu 		break;
362*91f16700Schasinglulu 
363*91f16700Schasinglulu 	case USB_REQ_RECIPIENT_ENDPOINT:
364*91f16700Schasinglulu 	default:
365*91f16700Schasinglulu 		ERROR("receive unsupported request %u",
366*91f16700Schasinglulu 		      pdev->request.bm_request & USB_REQ_RECIPIENT_MASK);
367*91f16700Schasinglulu 		usb_core_set_stall(pdev, pdev->request.bm_request & USB_REQ_DIRECTION);
368*91f16700Schasinglulu 		return USBD_FAIL;
369*91f16700Schasinglulu 	}
370*91f16700Schasinglulu 
371*91f16700Schasinglulu 	return USBD_OK;
372*91f16700Schasinglulu }
373*91f16700Schasinglulu 
374*91f16700Schasinglulu /*
375*91f16700Schasinglulu  * usb_core_data_out
376*91f16700Schasinglulu  *         Handle data OUT stage
377*91f16700Schasinglulu  * pdev: device instance
378*91f16700Schasinglulu  * epnum: endpoint index
379*91f16700Schasinglulu  * pdata: buffer to sent
380*91f16700Schasinglulu  * return : status
381*91f16700Schasinglulu  */
382*91f16700Schasinglulu static enum usb_status usb_core_data_out(struct usb_handle *pdev, uint8_t epnum,
383*91f16700Schasinglulu 					 uint8_t *pdata)
384*91f16700Schasinglulu {
385*91f16700Schasinglulu 	struct usb_endpoint *pep;
386*91f16700Schasinglulu 
387*91f16700Schasinglulu 	if (epnum == 0U) {
388*91f16700Schasinglulu 		pep = &pdev->ep_out[0];
389*91f16700Schasinglulu 		if (pdev->ep0_state == USBD_EP0_DATA_OUT) {
390*91f16700Schasinglulu 			if (pep->rem_length > pep->maxpacket) {
391*91f16700Schasinglulu 				pep->rem_length -= pep->maxpacket;
392*91f16700Schasinglulu 
393*91f16700Schasinglulu 				usb_core_receive(pdev, 0U, pdata,
394*91f16700Schasinglulu 						 MIN(pep->rem_length,
395*91f16700Schasinglulu 						     pep->maxpacket));
396*91f16700Schasinglulu 			} else {
397*91f16700Schasinglulu 				if (pdev->class->ep0_rx_ready &&
398*91f16700Schasinglulu 				    (pdev->dev_state == USBD_STATE_CONFIGURED)) {
399*91f16700Schasinglulu 					pdev->class->ep0_rx_ready(pdev);
400*91f16700Schasinglulu 				}
401*91f16700Schasinglulu 
402*91f16700Schasinglulu 				usb_core_transmit_ep0(pdev, NULL, 0U);
403*91f16700Schasinglulu 			}
404*91f16700Schasinglulu 		}
405*91f16700Schasinglulu 	} else if (pdev->class->data_out != NULL &&
406*91f16700Schasinglulu 		   (pdev->dev_state == USBD_STATE_CONFIGURED)) {
407*91f16700Schasinglulu 		pdev->class->data_out(pdev, epnum);
408*91f16700Schasinglulu 	}
409*91f16700Schasinglulu 
410*91f16700Schasinglulu 	return USBD_OK;
411*91f16700Schasinglulu }
412*91f16700Schasinglulu 
413*91f16700Schasinglulu /*
414*91f16700Schasinglulu  * usb_core_data_in
415*91f16700Schasinglulu  *         Handle data in stage
416*91f16700Schasinglulu  * pdev: device instance
417*91f16700Schasinglulu  * epnum: endpoint index
418*91f16700Schasinglulu  * pdata: buffer to fill
419*91f16700Schasinglulu  * return : status
420*91f16700Schasinglulu  */
421*91f16700Schasinglulu static enum usb_status usb_core_data_in(struct usb_handle *pdev, uint8_t epnum,
422*91f16700Schasinglulu 					uint8_t *pdata)
423*91f16700Schasinglulu {
424*91f16700Schasinglulu 	if (epnum == 0U) {
425*91f16700Schasinglulu 		struct usb_endpoint *pep = &pdev->ep_in[0];
426*91f16700Schasinglulu 
427*91f16700Schasinglulu 		if (pdev->ep0_state == USBD_EP0_DATA_IN) {
428*91f16700Schasinglulu 			if (pep->rem_length > pep->maxpacket) {
429*91f16700Schasinglulu 				pep->rem_length -= pep->maxpacket;
430*91f16700Schasinglulu 
431*91f16700Schasinglulu 				usb_core_transmit(pdev, 0U, pdata,
432*91f16700Schasinglulu 						  pep->rem_length);
433*91f16700Schasinglulu 
434*91f16700Schasinglulu 				/* Prepare EP for premature end of transfer */
435*91f16700Schasinglulu 				usb_core_receive(pdev, 0U, NULL, 0U);
436*91f16700Schasinglulu 			} else {
437*91f16700Schasinglulu 				/* Last packet is MPS multiple, send ZLP packet */
438*91f16700Schasinglulu 				if ((pep->total_length % pep->maxpacket == 0U) &&
439*91f16700Schasinglulu 				    (pep->total_length >= pep->maxpacket) &&
440*91f16700Schasinglulu 				    (pep->total_length < pdev->ep0_data_len)) {
441*91f16700Schasinglulu 					usb_core_transmit(pdev, 0U, NULL, 0U);
442*91f16700Schasinglulu 
443*91f16700Schasinglulu 					pdev->ep0_data_len = 0U;
444*91f16700Schasinglulu 
445*91f16700Schasinglulu 					/* Prepare endpoint for premature end of transfer */
446*91f16700Schasinglulu 					usb_core_receive(pdev, 0U, NULL, 0U);
447*91f16700Schasinglulu 				} else {
448*91f16700Schasinglulu 					if (pdev->class->ep0_tx_sent != NULL &&
449*91f16700Schasinglulu 					    (pdev->dev_state ==
450*91f16700Schasinglulu 					     USBD_STATE_CONFIGURED)) {
451*91f16700Schasinglulu 						pdev->class->ep0_tx_sent(pdev);
452*91f16700Schasinglulu 					}
453*91f16700Schasinglulu 					/* Start the transfer */
454*91f16700Schasinglulu 					usb_core_receive_ep0(pdev, NULL, 0U);
455*91f16700Schasinglulu 				}
456*91f16700Schasinglulu 			}
457*91f16700Schasinglulu 		}
458*91f16700Schasinglulu 	} else if ((pdev->class->data_in != NULL) &&
459*91f16700Schasinglulu 		  (pdev->dev_state == USBD_STATE_CONFIGURED)) {
460*91f16700Schasinglulu 		pdev->class->data_in(pdev, epnum);
461*91f16700Schasinglulu 	}
462*91f16700Schasinglulu 
463*91f16700Schasinglulu 	return USBD_OK;
464*91f16700Schasinglulu }
465*91f16700Schasinglulu 
466*91f16700Schasinglulu /*
467*91f16700Schasinglulu  * usb_core_suspend
468*91f16700Schasinglulu  *         Handle suspend event
469*91f16700Schasinglulu  * pdev : device instance
470*91f16700Schasinglulu  * return : status
471*91f16700Schasinglulu  */
472*91f16700Schasinglulu static enum usb_status usb_core_suspend(struct usb_handle  *pdev)
473*91f16700Schasinglulu {
474*91f16700Schasinglulu 	INFO("USB Suspend mode\n");
475*91f16700Schasinglulu 	pdev->dev_old_state =  pdev->dev_state;
476*91f16700Schasinglulu 	pdev->dev_state  = USBD_STATE_SUSPENDED;
477*91f16700Schasinglulu 
478*91f16700Schasinglulu 	return USBD_OK;
479*91f16700Schasinglulu }
480*91f16700Schasinglulu 
481*91f16700Schasinglulu /*
482*91f16700Schasinglulu  * usb_core_resume
483*91f16700Schasinglulu  *         Handle resume event
484*91f16700Schasinglulu  * pdev : device instance
485*91f16700Schasinglulu  * return : status
486*91f16700Schasinglulu  */
487*91f16700Schasinglulu static enum usb_status usb_core_resume(struct usb_handle *pdev)
488*91f16700Schasinglulu {
489*91f16700Schasinglulu 	INFO("USB Resume\n");
490*91f16700Schasinglulu 	pdev->dev_state = pdev->dev_old_state;
491*91f16700Schasinglulu 
492*91f16700Schasinglulu 	return USBD_OK;
493*91f16700Schasinglulu }
494*91f16700Schasinglulu 
495*91f16700Schasinglulu /*
496*91f16700Schasinglulu  * usb_core_sof
497*91f16700Schasinglulu  *         Handle SOF event
498*91f16700Schasinglulu  * pdev : device instance
499*91f16700Schasinglulu  * return : status
500*91f16700Schasinglulu  */
501*91f16700Schasinglulu static enum usb_status usb_core_sof(struct usb_handle *pdev)
502*91f16700Schasinglulu {
503*91f16700Schasinglulu 	if (pdev->dev_state == USBD_STATE_CONFIGURED) {
504*91f16700Schasinglulu 		if (pdev->class->sof != NULL) {
505*91f16700Schasinglulu 			pdev->class->sof(pdev);
506*91f16700Schasinglulu 		}
507*91f16700Schasinglulu 	}
508*91f16700Schasinglulu 
509*91f16700Schasinglulu 	return USBD_OK;
510*91f16700Schasinglulu }
511*91f16700Schasinglulu 
512*91f16700Schasinglulu /*
513*91f16700Schasinglulu  * usb_core_disconnect
514*91f16700Schasinglulu  *         Handle device disconnection event
515*91f16700Schasinglulu  * pdev : device instance
516*91f16700Schasinglulu  * return : status
517*91f16700Schasinglulu  */
518*91f16700Schasinglulu static enum usb_status usb_core_disconnect(struct usb_handle *pdev)
519*91f16700Schasinglulu {
520*91f16700Schasinglulu 	/* Free class resources */
521*91f16700Schasinglulu 	pdev->dev_state = USBD_STATE_DEFAULT;
522*91f16700Schasinglulu 	pdev->class->de_init(pdev, pdev->dev_config);
523*91f16700Schasinglulu 
524*91f16700Schasinglulu 	return USBD_OK;
525*91f16700Schasinglulu }
526*91f16700Schasinglulu 
527*91f16700Schasinglulu enum usb_status usb_core_handle_it(struct usb_handle *pdev)
528*91f16700Schasinglulu {
529*91f16700Schasinglulu 	uint32_t param = 0U;
530*91f16700Schasinglulu 	uint32_t len = 0U;
531*91f16700Schasinglulu 	struct usbd_ep *ep;
532*91f16700Schasinglulu 
533*91f16700Schasinglulu 	switch (pdev->driver->it_handler(pdev->data->instance, &param)) {
534*91f16700Schasinglulu 	case USB_DATA_OUT:
535*91f16700Schasinglulu 		usb_core_data_out(pdev, param,
536*91f16700Schasinglulu 				  pdev->data->out_ep[param].xfer_buff);
537*91f16700Schasinglulu 		break;
538*91f16700Schasinglulu 
539*91f16700Schasinglulu 	case USB_DATA_IN:
540*91f16700Schasinglulu 		usb_core_data_in(pdev, param,
541*91f16700Schasinglulu 				 pdev->data->in_ep[param].xfer_buff);
542*91f16700Schasinglulu 		break;
543*91f16700Schasinglulu 
544*91f16700Schasinglulu 	case USB_SETUP:
545*91f16700Schasinglulu 		usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup);
546*91f16700Schasinglulu 		break;
547*91f16700Schasinglulu 
548*91f16700Schasinglulu 	case USB_ENUM_DONE:
549*91f16700Schasinglulu 		break;
550*91f16700Schasinglulu 
551*91f16700Schasinglulu 	case USB_READ_DATA_PACKET:
552*91f16700Schasinglulu 		ep = &pdev->data->out_ep[param &  USBD_OUT_EPNUM_MASK];
553*91f16700Schasinglulu 		len = (param &  USBD_OUT_COUNT_MASK) >> USBD_OUT_COUNT_SHIFT;
554*91f16700Schasinglulu 		pdev->driver->read_packet(pdev->data->instance,
555*91f16700Schasinglulu 					  ep->xfer_buff, len);
556*91f16700Schasinglulu 		ep->xfer_buff += len;
557*91f16700Schasinglulu 		ep->xfer_count += len;
558*91f16700Schasinglulu 		break;
559*91f16700Schasinglulu 
560*91f16700Schasinglulu 	case USB_READ_SETUP_PACKET:
561*91f16700Schasinglulu 		ep = &pdev->data->out_ep[param &  USBD_OUT_EPNUM_MASK];
562*91f16700Schasinglulu 		len = (param &  USBD_OUT_COUNT_MASK) >> 0x10;
563*91f16700Schasinglulu 		pdev->driver->read_packet(pdev->data->instance,
564*91f16700Schasinglulu 					  (uint8_t *)pdev->data->setup, 8);
565*91f16700Schasinglulu 		ep->xfer_count += len;
566*91f16700Schasinglulu 		break;
567*91f16700Schasinglulu 
568*91f16700Schasinglulu 	case USB_RESET:
569*91f16700Schasinglulu 		pdev->dev_state = USBD_STATE_DEFAULT;
570*91f16700Schasinglulu 		break;
571*91f16700Schasinglulu 
572*91f16700Schasinglulu 	case USB_RESUME:
573*91f16700Schasinglulu 		if (pdev->data->lpm_state == LPM_L1) {
574*91f16700Schasinglulu 			pdev->data->lpm_state = LPM_L0;
575*91f16700Schasinglulu 		} else {
576*91f16700Schasinglulu 			usb_core_resume(pdev);
577*91f16700Schasinglulu 		}
578*91f16700Schasinglulu 		break;
579*91f16700Schasinglulu 
580*91f16700Schasinglulu 	case USB_SUSPEND:
581*91f16700Schasinglulu 		usb_core_suspend(pdev);
582*91f16700Schasinglulu 		break;
583*91f16700Schasinglulu 
584*91f16700Schasinglulu 	case USB_LPM:
585*91f16700Schasinglulu 		if (pdev->data->lpm_state == LPM_L0) {
586*91f16700Schasinglulu 			pdev->data->lpm_state = LPM_L1;
587*91f16700Schasinglulu 		} else {
588*91f16700Schasinglulu 			usb_core_suspend(pdev);
589*91f16700Schasinglulu 		}
590*91f16700Schasinglulu 		break;
591*91f16700Schasinglulu 
592*91f16700Schasinglulu 	case USB_SOF:
593*91f16700Schasinglulu 		usb_core_sof(pdev);
594*91f16700Schasinglulu 		break;
595*91f16700Schasinglulu 
596*91f16700Schasinglulu 	case USB_DISCONNECT:
597*91f16700Schasinglulu 		usb_core_disconnect(pdev);
598*91f16700Schasinglulu 		break;
599*91f16700Schasinglulu 
600*91f16700Schasinglulu 	case USB_WRITE_EMPTY:
601*91f16700Schasinglulu 		pdev->driver->write_empty_tx_fifo(pdev->data->instance, param,
602*91f16700Schasinglulu 				     pdev->data->in_ep[param].xfer_len,
603*91f16700Schasinglulu 				     (uint32_t *)&pdev->data->in_ep[param].xfer_count,
604*91f16700Schasinglulu 				     pdev->data->in_ep[param].maxpacket,
605*91f16700Schasinglulu 				     &pdev->data->in_ep[param].xfer_buff);
606*91f16700Schasinglulu 		break;
607*91f16700Schasinglulu 
608*91f16700Schasinglulu 	case USB_NOTHING:
609*91f16700Schasinglulu 	default:
610*91f16700Schasinglulu 		break;
611*91f16700Schasinglulu 	}
612*91f16700Schasinglulu 
613*91f16700Schasinglulu 	return USBD_OK;
614*91f16700Schasinglulu }
615*91f16700Schasinglulu 
616*91f16700Schasinglulu static void usb_core_start_xfer(struct usb_handle *pdev,
617*91f16700Schasinglulu 				void *handle,
618*91f16700Schasinglulu 				struct usbd_ep *ep)
619*91f16700Schasinglulu {
620*91f16700Schasinglulu 	if (ep->num == 0U) {
621*91f16700Schasinglulu 		pdev->driver->ep0_start_xfer(handle, ep);
622*91f16700Schasinglulu 	} else {
623*91f16700Schasinglulu 		pdev->driver->ep_start_xfer(handle, ep);
624*91f16700Schasinglulu 	}
625*91f16700Schasinglulu }
626*91f16700Schasinglulu 
627*91f16700Schasinglulu /*
628*91f16700Schasinglulu  * usb_core_receive
629*91f16700Schasinglulu  *          Receive an amount of data
630*91f16700Schasinglulu  * pdev: USB handle
631*91f16700Schasinglulu  * ep_addr: endpoint address
632*91f16700Schasinglulu  * buf: pointer to the reception buffer
633*91f16700Schasinglulu  * len: amount of data to be received
634*91f16700Schasinglulu  * return : status
635*91f16700Schasinglulu  */
636*91f16700Schasinglulu enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr,
637*91f16700Schasinglulu 				 uint8_t *buf, uint32_t len)
638*91f16700Schasinglulu {
639*91f16700Schasinglulu 	struct usbd_ep *ep;
640*91f16700Schasinglulu 	struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
641*91f16700Schasinglulu 	uint8_t num;
642*91f16700Schasinglulu 
643*91f16700Schasinglulu 	num = ep_addr & EP_NUM_MASK;
644*91f16700Schasinglulu 	if (num >= USBD_EP_NB) {
645*91f16700Schasinglulu 		return USBD_FAIL;
646*91f16700Schasinglulu 	}
647*91f16700Schasinglulu 	ep = &hpcd->out_ep[num];
648*91f16700Schasinglulu 
649*91f16700Schasinglulu 	/* Setup and start the Xfer */
650*91f16700Schasinglulu 	ep->xfer_buff = buf;
651*91f16700Schasinglulu 	ep->xfer_len = len;
652*91f16700Schasinglulu 	ep->xfer_count = 0U;
653*91f16700Schasinglulu 	ep->is_in = false;
654*91f16700Schasinglulu 	ep->num = num;
655*91f16700Schasinglulu 
656*91f16700Schasinglulu 	usb_core_start_xfer(pdev, hpcd->instance, ep);
657*91f16700Schasinglulu 
658*91f16700Schasinglulu 	return USBD_OK;
659*91f16700Schasinglulu }
660*91f16700Schasinglulu 
661*91f16700Schasinglulu /*
662*91f16700Schasinglulu  * usb_core_transmit
663*91f16700Schasinglulu  *          Send an amount of data
664*91f16700Schasinglulu  * pdev: USB handle
665*91f16700Schasinglulu  * ep_addr: endpoint address
666*91f16700Schasinglulu  * buf: pointer to the transmission buffer
667*91f16700Schasinglulu  * len: amount of data to be sent
668*91f16700Schasinglulu  * return : status
669*91f16700Schasinglulu  */
670*91f16700Schasinglulu enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr,
671*91f16700Schasinglulu 				  uint8_t *buf, uint32_t len)
672*91f16700Schasinglulu {
673*91f16700Schasinglulu 	struct usbd_ep *ep;
674*91f16700Schasinglulu 	struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
675*91f16700Schasinglulu 	uint8_t num;
676*91f16700Schasinglulu 
677*91f16700Schasinglulu 	num = ep_addr & EP_NUM_MASK;
678*91f16700Schasinglulu 	if (num >= USBD_EP_NB) {
679*91f16700Schasinglulu 		return USBD_FAIL;
680*91f16700Schasinglulu 	}
681*91f16700Schasinglulu 	ep = &hpcd->in_ep[num];
682*91f16700Schasinglulu 
683*91f16700Schasinglulu 	/* Setup and start the Xfer */
684*91f16700Schasinglulu 	ep->xfer_buff = buf;
685*91f16700Schasinglulu 	ep->xfer_len = len;
686*91f16700Schasinglulu 	ep->xfer_count = 0U;
687*91f16700Schasinglulu 	ep->is_in = true;
688*91f16700Schasinglulu 	ep->num = num;
689*91f16700Schasinglulu 
690*91f16700Schasinglulu 	usb_core_start_xfer(pdev, hpcd->instance, ep);
691*91f16700Schasinglulu 
692*91f16700Schasinglulu 	return USBD_OK;
693*91f16700Schasinglulu }
694*91f16700Schasinglulu 
695*91f16700Schasinglulu /*
696*91f16700Schasinglulu  * usb_core_receive_ep0
697*91f16700Schasinglulu  *          Receive an amount of data on ep0
698*91f16700Schasinglulu  * pdev: USB handle
699*91f16700Schasinglulu  * buf: pointer to the reception buffer
700*91f16700Schasinglulu  * len: amount of data to be received
701*91f16700Schasinglulu  * return : status
702*91f16700Schasinglulu  */
703*91f16700Schasinglulu enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *buf,
704*91f16700Schasinglulu 				     uint32_t len)
705*91f16700Schasinglulu {
706*91f16700Schasinglulu 	/* Prepare the reception of the buffer over EP0 */
707*91f16700Schasinglulu 	if (len != 0U) {
708*91f16700Schasinglulu 		pdev->ep0_state = USBD_EP0_DATA_OUT;
709*91f16700Schasinglulu 	} else {
710*91f16700Schasinglulu 		pdev->ep0_state = USBD_EP0_STATUS_OUT;
711*91f16700Schasinglulu 	}
712*91f16700Schasinglulu 
713*91f16700Schasinglulu 	pdev->ep_out[0].total_length = len;
714*91f16700Schasinglulu 	pdev->ep_out[0].rem_length = len;
715*91f16700Schasinglulu 
716*91f16700Schasinglulu 	/* Start the transfer */
717*91f16700Schasinglulu 	return usb_core_receive(pdev, 0U, buf, len);
718*91f16700Schasinglulu }
719*91f16700Schasinglulu 
720*91f16700Schasinglulu /*
721*91f16700Schasinglulu  * usb_core_transmit_ep0
722*91f16700Schasinglulu  *          Send an amount of data on ep0
723*91f16700Schasinglulu  * pdev: USB handle
724*91f16700Schasinglulu  * buf: pointer to the transmission buffer
725*91f16700Schasinglulu  * len: amount of data to be sent
726*91f16700Schasinglulu  * return : status
727*91f16700Schasinglulu  */
728*91f16700Schasinglulu enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *buf,
729*91f16700Schasinglulu 				      uint32_t len)
730*91f16700Schasinglulu {
731*91f16700Schasinglulu 	/* Set EP0 State */
732*91f16700Schasinglulu 	if (len != 0U) {
733*91f16700Schasinglulu 		pdev->ep0_state = USBD_EP0_DATA_IN;
734*91f16700Schasinglulu 	} else {
735*91f16700Schasinglulu 		pdev->ep0_state = USBD_EP0_STATUS_IN;
736*91f16700Schasinglulu 	}
737*91f16700Schasinglulu 
738*91f16700Schasinglulu 	pdev->ep_in[0].total_length = len;
739*91f16700Schasinglulu 	pdev->ep_in[0].rem_length = len;
740*91f16700Schasinglulu 
741*91f16700Schasinglulu 	/* Start the transfer */
742*91f16700Schasinglulu 	return usb_core_transmit(pdev, 0U, buf, len);
743*91f16700Schasinglulu }
744*91f16700Schasinglulu 
745*91f16700Schasinglulu /*
746*91f16700Schasinglulu  * usb_core_ctl_error
747*91f16700Schasinglulu  *         Handle USB low level error
748*91f16700Schasinglulu  * pdev: device instance
749*91f16700Schasinglulu  * req: usb request
750*91f16700Schasinglulu  * return : None
751*91f16700Schasinglulu  */
752*91f16700Schasinglulu 
753*91f16700Schasinglulu void usb_core_ctl_error(struct usb_handle *pdev)
754*91f16700Schasinglulu {
755*91f16700Schasinglulu 	ERROR("%s : Send an ERROR\n", __func__);
756*91f16700Schasinglulu 	usb_core_set_stall(pdev, EP0_IN);
757*91f16700Schasinglulu 	usb_core_set_stall(pdev, EP0_OUT);
758*91f16700Schasinglulu }
759*91f16700Schasinglulu 
760*91f16700Schasinglulu /*
761*91f16700Schasinglulu  * usb_core_start
762*91f16700Schasinglulu  *         Start the USB device core.
763*91f16700Schasinglulu  * pdev: Device Handle
764*91f16700Schasinglulu  * return : USBD Status
765*91f16700Schasinglulu  */
766*91f16700Schasinglulu enum usb_status usb_core_start(struct usb_handle *pdev)
767*91f16700Schasinglulu {
768*91f16700Schasinglulu 	/* Start the low level driver */
769*91f16700Schasinglulu 	pdev->driver->start_device(pdev->data->instance);
770*91f16700Schasinglulu 
771*91f16700Schasinglulu 	return USBD_OK;
772*91f16700Schasinglulu }
773*91f16700Schasinglulu 
774*91f16700Schasinglulu /*
775*91f16700Schasinglulu  * usb_core_stop
776*91f16700Schasinglulu  *         Stop the USB device core.
777*91f16700Schasinglulu  * pdev: Device Handle
778*91f16700Schasinglulu  * return : USBD Status
779*91f16700Schasinglulu  */
780*91f16700Schasinglulu enum usb_status usb_core_stop(struct usb_handle *pdev)
781*91f16700Schasinglulu {
782*91f16700Schasinglulu 	/* Free class resources */
783*91f16700Schasinglulu 	pdev->class->de_init(pdev, pdev->dev_config);
784*91f16700Schasinglulu 
785*91f16700Schasinglulu 	/* Stop the low level driver */
786*91f16700Schasinglulu 	pdev->driver->stop_device(pdev->data->instance);
787*91f16700Schasinglulu 
788*91f16700Schasinglulu 	return USBD_OK;
789*91f16700Schasinglulu }
790*91f16700Schasinglulu 
791*91f16700Schasinglulu /*
792*91f16700Schasinglulu  * register_usb_driver
793*91f16700Schasinglulu  *         Stop the USB device core.
794*91f16700Schasinglulu  * pdev: Device Handle
795*91f16700Schasinglulu  * pcd_handle: PCD handle
796*91f16700Schasinglulu  * driver: USB driver
797*91f16700Schasinglulu  * driver_handle: USB driver handle
798*91f16700Schasinglulu  * return : USBD Status
799*91f16700Schasinglulu  */
800*91f16700Schasinglulu enum usb_status register_usb_driver(struct usb_handle *pdev,
801*91f16700Schasinglulu 				    struct pcd_handle *pcd_handle,
802*91f16700Schasinglulu 				    const struct usb_driver *driver,
803*91f16700Schasinglulu 				    void *driver_handle)
804*91f16700Schasinglulu {
805*91f16700Schasinglulu 	uint8_t i;
806*91f16700Schasinglulu 
807*91f16700Schasinglulu 	assert(pdev != NULL);
808*91f16700Schasinglulu 	assert(pcd_handle != NULL);
809*91f16700Schasinglulu 	assert(driver != NULL);
810*91f16700Schasinglulu 	assert(driver_handle != NULL);
811*91f16700Schasinglulu 
812*91f16700Schasinglulu 	/* Free class resources */
813*91f16700Schasinglulu 	pdev->driver = driver;
814*91f16700Schasinglulu 	pdev->data = pcd_handle;
815*91f16700Schasinglulu 	pdev->data->instance = driver_handle;
816*91f16700Schasinglulu 	pdev->dev_state = USBD_STATE_DEFAULT;
817*91f16700Schasinglulu 	pdev->ep0_state = USBD_EP0_IDLE;
818*91f16700Schasinglulu 
819*91f16700Schasinglulu 	/* Copy endpoint information */
820*91f16700Schasinglulu 	for (i = 0U; i < USBD_EP_NB; i++) {
821*91f16700Schasinglulu 		pdev->ep_in[i].maxpacket = pdev->data->in_ep[i].maxpacket;
822*91f16700Schasinglulu 		pdev->ep_out[i].maxpacket = pdev->data->out_ep[i].maxpacket;
823*91f16700Schasinglulu 	}
824*91f16700Schasinglulu 
825*91f16700Schasinglulu 	return USBD_OK;
826*91f16700Schasinglulu }
827*91f16700Schasinglulu 
828*91f16700Schasinglulu /*
829*91f16700Schasinglulu  * register_platform
830*91f16700Schasinglulu  *         Register the USB device core.
831*91f16700Schasinglulu  * pdev: Device Handle
832*91f16700Schasinglulu  * plat_call_back: callback
833*91f16700Schasinglulu  * return : USBD Status
834*91f16700Schasinglulu  */
835*91f16700Schasinglulu enum usb_status register_platform(struct usb_handle *pdev,
836*91f16700Schasinglulu 			       const struct usb_desc *plat_call_back)
837*91f16700Schasinglulu {
838*91f16700Schasinglulu 	assert(pdev != NULL);
839*91f16700Schasinglulu 	assert(plat_call_back != NULL);
840*91f16700Schasinglulu 
841*91f16700Schasinglulu 	/* Save platform info in class resources */
842*91f16700Schasinglulu 	pdev->desc = plat_call_back;
843*91f16700Schasinglulu 
844*91f16700Schasinglulu 	return USBD_OK;
845*91f16700Schasinglulu }
846