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