1/**************************************************************************** 2 * drivers/usbdev/composite.c 3 * 4 * Copyright (C) 2012, 2016-2017 Gregory Nutt. All rights reserved. 5 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved. 6 * Author: Gregory Nutt <gnutt@nuttx.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name NuttX nor the names of its contributors may be 19 * used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 * 35 ****************************************************************************/ 36/**************************************************************************** 37 * Notice of Export Control Law 38 * =============================================== 39 * Huawei LiteOS may be subject to applicable export control laws and regulations, 40 * which might include those applicable to Huawei LiteOS of U.S. and the country in 41 * which you are located. 42 * Import, export and usage of Huawei LiteOS in any manner by you shall be in 43 * compliance with such applicable export control laws and regulations. 44 ****************************************************************************/ 45 46/**************************************************************************** 47 * Included Files 48 ****************************************************************************/ 49#include "los_vm_iomap.h" 50#include "gadget/composite.h" 51#define FCOFNIG_FUN 52 53#undef USB_DEBUG_VAR 54#define USB_DEBUG_VAR g_composite_debug 55#ifdef LOSCFG_USB_DEBUG 56static int g_composite_debug = 0; 57void usb_composite_debug_func(int level) 58{ 59 g_composite_debug = level; 60 PRINTK("The level of usb composite debug is %d\n", level); 61} 62DEBUG_MODULE(composite, usb_composite_debug_func); 63#endif 64 65int composite_device_init(struct composite_softc *cdev); 66 67static const uint8_t g_bos_desc_buf[22] = 68{ 69 5, 0xf, 0x16, 0, 2, 7, 0x10, 2, 6, 0, 0, 0, 70 0xa, 0x10, 3, 0, 0xf, 0, 1, 1, 0xf4, 1 71}; 72 73static device_probe_t composite_probe; 74static device_attach_t composite_attach; 75static device_detach_t composite_detach; 76static devclass_t composite_devclass; 77 78static device_method_t g_composite_methods[] = 79{ 80 /* Device interface */ 81 82 DEVMETHOD(device_probe, composite_probe), 83 DEVMETHOD(device_attach, composite_attach), 84 DEVMETHOD(device_detach, composite_detach), 85 DEVMETHOD_END 86}; 87 88static driver_t g_composite_driver = 89{ 90 .name = "composite", 91 .methods = g_composite_methods, 92 .size = sizeof(struct composite_softc) 93}; 94 95DRIVER_MODULE(composite, hiudc3, g_composite_driver, composite_devclass, NULL, NULL); 96 97void usbd_configep_byspeed(struct usbdev_s *dev, struct usb_endpoint_descriptor *ep_desc) 98{ 99 if (ep_desc->bmAttributes == UE_BULK) 100 { 101 switch (dev->speed) 102 { 103 case USB_SPEED_SUPER: 104 USETW(ep_desc->wMaxPacketSize, USB_DWC_MAX_PACKET_SIZE); 105 break; 106 107 case USB_SPEED_HIGH: 108 USETW(ep_desc->wMaxPacketSize, USB_DWC_U2_MAX_PACKET_SIZE); 109 break; 110 111 default: 112 PRINT_ERR("%s invalid speed:%u\r\n", __FUNCTION__, dev->speed); 113 break; 114 } 115 } 116 117 return; 118} 119 120void composite_request_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req) 121{ 122 (void)ep; 123 (void)req; 124} 125 126static struct usbdev_req_s *composite_allocreq(uint16_t len) 127{ 128 DMA_ADDR_T paddr; 129 struct usbdev_req_s *req = zalloc(sizeof(struct usbdev_req_s)); 130 if (req != NULL) 131 { 132 req->len = len; 133 req->buf = (uint8_t *)LOS_DmaMemAlloc(&paddr, len, USB_CACHE_ALIGN_SIZE, DMA_NOCACHE); 134 if (req->buf == NULL) 135 { 136 free(req); 137 return NULL; 138 } 139 req->dma = (DMA_ADDR_T)VMM_TO_UNCACHED_ADDR((unsigned long)req->buf); 140 } 141 142 return req; 143} 144 145static void composite_freereq(struct usbdev_req_s *req) 146{ 147 if (req != NULL) 148 { 149 if (req->buf != NULL) 150 { 151 (VOID)LOS_DmaMemFree(req->buf); 152 req->buf = NULL; 153 } 154 free(req); 155 } 156} 157 158static int usb_composite_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 159{ 160 struct composite_dev_s *cdev; 161 int ret; 162 163 if (driver == NULL || dev == NULL) 164 { 165 PRINT_ERR("unbind fail, invalid gadget\n"); 166 return -1; 167 } 168 169 cdev = ((struct composite_driver_s *)driver)->dev; 170 171 /* Make sure that we are not already unbound */ 172 173 if (cdev != NULL) 174 { 175 int i; 176 177 /* Unbind the constituent class drivers */ 178 179 for (i = 0; i < cdev->ndevices; i++) 180 { 181 ret = CLASS_UNBIND(cdev->device[i].dev, dev); 182 if (ret < 0) 183 { 184 PRINT_ERR("unbind gadget fail, busy!\n"); 185 return -1; 186 } 187 } 188 189 /* Free the pre-allocated control request */ 190 191 cdev->config = COMPOSITE_CONFIGIDNONE; 192 composite_freereq(cdev->ctrlreq); 193 cdev->ctrlreq = NULL; 194 cdev->usbdev = NULL; 195 } 196 dev->ep0->priv = NULL; 197 198 return 0; 199} 200 201static int usb_composite_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 202{ 203 struct composite_dev_s *cdev; 204 int ret; 205 int i; 206 207 if (driver == NULL || dev == NULL) 208 { 209 return -1; 210 } 211 cdev = ((struct composite_driver_s *)driver)->dev; 212 if (cdev == NULL) 213 { 214 PRINT_ERR("cdev == NULL\n"); 215 return -1; 216 } 217 218 /* Bind the structures */ 219 220 cdev->usbdev = dev; 221 222 /* initialize ctrlreq and allocate memory for it's buf */ 223 224 cdev->ctrlreq = composite_allocreq(USB_COMP_EP0_BUFSIZ); 225 if (cdev->ctrlreq == NULL) 226 { 227 PRINT_ERR("%s malloc control request buf failed!\n", __FUNCTION__); 228 goto failed; 229 } 230 dev->ep0->handle_req = cdev->ctrlreq; 231 cdev->ctrlreq->callback = composite_request_complete; 232 233 /* Save the reference to our private data structure in EP0 so that it 234 * can be recovered in ep0 completion events. 235 */ 236 dev->ep0->priv = cdev; 237 for (i = 0; i < cdev->ndevices; i++) 238 { 239 ret = CLASS_BIND(cdev->device[i].dev, dev); 240 if (ret < 0) 241 { 242 PRINT_ERR(" composite device bind gadget failed!\n"); 243 goto failed; 244 } 245 } 246 247 DPRINTF("composite bind device success!\n"); 248 return 0; 249 250failed: 251 (void)usb_composite_unbind(driver, dev); 252 return -1; 253} 254 255static int modify_config_descriptor_byspeed(struct usbdev_s *dev, struct usbdev_req_s *req) 256{ 257 struct usb_descriptor *descriptors; 258 uint32_t config_len = req->len; 259 uint32_t new_config_len; 260 uint8_t *config_tmp_buf; 261 struct usb_config_descriptor *config_des; 262 uint32_t i; 263 int ret; 264 265 if (dev->speed != USB_SPEED_SUPER && dev->speed != USB_SPEED_HIGH) 266 { 267 usb_err("Device controller speed can not support!\n"); 268 return -EINVAL; 269 } 270 271 if (dev->speed == USB_SPEED_SUPER) 272 { 273 return 0; /* The configuration descriptor defaults to the superspeed form. */ 274 } 275 276 config_tmp_buf = malloc(config_len); 277 if (config_tmp_buf == NULL) 278 { 279 usb_err("malloc failed\n"); 280 return -ENOMEM; 281 } 282 283 ret = memset_s(config_tmp_buf, config_len, 0, config_len); 284 if (ret != EOK) 285 { 286 usb_err("memset_s failed, %d\n", ret); 287 goto err; 288 } 289 290 descriptors = (struct usb_descriptor *)req->buf; 291 i = 0; 292 new_config_len = 0; 293 while (i < config_len) 294 { 295 i += descriptors->bLength; 296 if (descriptors->bDescriptorType != UDESC_ENDPOINT_SS_COMP) 297 { 298 ret = memcpy_s(config_tmp_buf + new_config_len, config_len - new_config_len, 299 descriptors, descriptors->bLength); 300 if (ret != EOK) 301 { 302 usb_err("memcpy_s failed, %d\n", ret); 303 goto err; 304 } 305 new_config_len += descriptors->bLength; 306 } 307 descriptors = (struct usb_descriptor *)((char *)descriptors + descriptors->bLength); 308 } 309 ret = memset_s(req->buf, USB_COMP_EP0_BUFSIZ, 0, config_len); 310 if (ret != EOK) 311 { 312 usb_err("memset_s failed, %d\n", ret); 313 goto err; 314 } 315 316 ret = memcpy_s(req->buf, USB_COMP_EP0_BUFSIZ, config_tmp_buf, new_config_len); 317 if (ret != EOK) 318 { 319 usb_err("memcpy_s failed, %d\n", ret); 320 goto err; 321 } 322 323 config_des = (struct usb_config_descriptor *)req->buf; 324 USETW(config_des->wTotalLength, new_config_len); 325 req->len = new_config_len; 326 free(config_tmp_buf); 327 328 return 0; 329 330err: 331 free(config_tmp_buf); 332 return -EINVAL; 333} 334 335int composite_get_config_descriptor(struct usbdev_s *dev, 336 struct usbdev_req_s *req, unsigned len) 337{ 338 int retval; 339 struct usb_descriptor *descriptors; 340 struct usb_endpoint_descriptor *ep_des; 341 int ret; 342 int i = 0; 343 344 ret = modify_config_descriptor_byspeed(dev, req); 345 if (ret < 0) 346 { 347 return -1; 348 } 349 350 retval = min(len, req->len); 351 descriptors = (struct usb_descriptor *)req->buf; 352 353 while (i < retval) 354 { 355 i += descriptors->bLength; 356 if (descriptors->bDescriptorType != UDESC_ENDPOINT) 357 { 358 descriptors = (struct usb_descriptor *)((char *)descriptors + descriptors->bLength); 359 continue; 360 } 361 362 ep_des = (struct usb_endpoint_descriptor *)descriptors; 363 usbd_configep_byspeed(dev, ep_des); 364 descriptors = (struct usb_descriptor *)((char *)descriptors + descriptors->bLength); 365 } 366 367 req->len = retval; 368 return retval; 369} 370 371void modify_device_descriptor_byspeed(struct usbdev_s *dev, uint8_t *buf) 372{ 373 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)buf; 374 switch (dev->speed) 375 { 376 case USB_SPEED_SUPER: 377 USETW(desc->bcdUSB, 0x0300); 378 desc->bMaxPacketSize = 0x09; 379 break; 380 381 case USB_SPEED_HIGH: 382 USETW(desc->bcdUSB, 0x0200); 383 desc->bMaxPacketSize = 0x40; 384 break; 385 386 default: 387 usb_err("invalid speed:%u\n", dev->speed); 388 break; 389 } 390} 391 392static int composite_classsetup(struct composite_dev_s *priv, 393 struct usbdev_s *dev, 394 const struct usb_device_request *ctrl, 395 uint8_t *dataout, size_t outlen) 396{ 397 struct composite_devobj_s *devobj; 398 struct usbdev_devinfo_s *devinfo; 399 uint16_t index; 400 uint8_t interface; 401 int ret = -EOPNOTSUPP; 402 int i; 403 int j; 404 405 (void)dataout; 406 (void)outlen; 407 408 index = UGETW(ctrl->wIndex); 409 interface = (uint8_t)(index & 0xff); 410 411 /* Usb standard protocol logic processing, such as set interface. */ 412 413 for (i = 0; i < priv->ndevices; i++) 414 { 415 if (interface >= priv->device[i].compdesc.devinfo.ifnobase && 416 interface < (priv->device[i].compdesc.devinfo.ifnobase + 417 priv->device[i].compdesc.devinfo.ninterfaces)) 418 { 419 ret = CLASS_SETUP(priv->device[i].dev, dev, ctrl, dataout, outlen); 420 return ret; 421 } 422 } 423 424 /* Specific protocol logic processing, such as UAC class setup. */ 425 426 for (i = 0; i < priv->ndevices; i++) 427 { 428 devobj = &priv->device[i]; 429 devinfo = &devobj->compdesc.devinfo; 430 for (j = 0; j < USBDEV_MAX_EPNUM; j++) 431 { 432 if (devinfo->epno[j] == interface) 433 { 434 ret = CLASS_SETUP(devobj->dev, dev, ctrl, dataout, outlen); 435 break; 436 } 437 } 438 } 439 440 return ret; 441} 442 443static void composite_setup_complete(struct usbdev_ep_s *ep, 444 struct usbdev_req_s *req) 445{ 446 (void)ep; 447 (void)req; 448} 449 450int usb_composite_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev, 451 const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen) 452{ 453 int ret = -1; 454 int value = 0; 455 int new_req = 0; 456 uint16_t w_value, w_length, w_Index; 457 struct composite_driver_s *driv; 458 struct composite_dev_s *usb_cdev; 459 struct usbdev_req_s *usb_req; 460 int i; 461 462 if (driver == NULL || ctrl == NULL || dev == NULL) 463 { 464 return -1; 465 } 466 467 driv = (struct composite_driver_s *)driver; 468 usb_cdev = driv->dev; 469 if (usb_cdev == NULL) 470 { 471 return -1; 472 } 473 474 w_value = UGETW(ctrl->wValue); 475 w_length = UGETW(ctrl->wLength); 476 w_Index = UGETW(ctrl->wIndex); 477 478 usb_req = usb_cdev->ctrlreq; 479 480 /* Update in the 'setup' function of a specific protocol, or use the default */ 481 usb_req->callback = composite_setup_complete; 482 usb_req->len = 0; 483 484 switch (ctrl->bRequest) 485 { 486 case USB_REQ_GET_DESCRIPTOR: 487 { 488 if (ctrl->bmRequestType != USB_DIR_IN) 489 { 490 goto unknowned; 491 } 492 493 switch (w_value >> 8) 494 { 495 case UDESC_DEVICE: 496 value = MIN(w_length, (UINT16)sizeof(struct usb_device_descriptor)); 497 composite_mkdevdesc(usb_cdev, usb_req->buf); 498 modify_device_descriptor_byspeed(dev, usb_req->buf); 499 usb_req->len = value; 500 new_req = 1; 501 break; 502 503 case UDESC_CONFIG: 504 value = composite_mkcfgdesc(usb_cdev, usb_req->buf); 505 if (value < 0) 506 { 507 break; 508 } 509 usb_req->len = value; 510 (void)composite_get_config_descriptor(dev, usb_req, w_length); 511 new_req = 1; 512 break; 513 514 case UDESC_STRING: 515 value = composite_mkstrdesc(usb_cdev, (w_value & 0xff), w_Index, usb_req->buf); 516 if (value < 0) 517 { 518 break; 519 } 520 usb_req->len = MIN(w_length, value); 521 new_req = 1; 522 break; 523 524 case UDESC_BOS: 525 usb_req->len = w_length; 526 ret = memcpy_s(usb_req->buf, USB_COMP_EP0_BUFSIZ, (void *)g_bos_desc_buf, SKB_DATA_ALIGN(usb_req->len)); 527 if (ret < 0) 528 { 529 return -1; 530 } 531 new_req = 1; 532 break; 533 534 default: 535 break; 536 } 537 } 538 break; 539 540 case USB_REQ_SET_CONFIGURATION: 541 { 542 if (ctrl->bmRequestType != USB_DIR_OUT) 543 { 544 goto unknowned; 545 } 546 dprintf("SET_CONFIGURATION\n"); 547 /* Save the configuration and inform the constituent classes */ 548 for (i = 0; i < usb_cdev->ndevices; i++) 549 { 550 ret = CLASS_SETUP(usb_cdev->device[i].dev, dev, ctrl, dataout, outlen); 551 if (ret < 0) 552 { 553 PRINT_ERR("set config fail!\n"); 554 return -1; 555 } 556 } 557 558 /* the ret of usbclass_mass_set_alt is '1', the invoking of usbd_endpoint_request is fmass's protocal */ 559 if (ret == 0) 560 { 561 new_req = 1; 562 } 563 usb_req->len = 0; 564 usb_cdev->config = w_value; 565 } 566 break; 567 568 case USB_REQ_GET_CONFIGURATION: 569 { 570 dprintf("%s, USB_REQ_GET_CONFIGURATION\n", __func__); 571 usb_req->len = 1; 572 usb_req->buf[0] = 1; 573 new_req = 1; 574 break; 575 } 576 577 case USB_REQ_SET_INTERFACE: 578 { 579 if (ctrl->bmRequestType == USB_RECIP_INTERFACE && 580 usb_cdev->config == COMPOSITE_CONFIGID) 581 { 582 value = composite_classsetup(usb_cdev, dev, ctrl, dataout, outlen); 583 new_req = 1; 584 } 585 break; 586 } 587 588 case USB_REQ_GET_STATUS: 589 { 590 if (ctrl->bmRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE)) 591 { 592 goto unknowned; 593 } 594 595 break; 596 } 597 598 case USB_REQ_CLEAR_FEATURE: 599 case USB_REQ_SET_FEATURE: 600 { 601 if (ctrl->bmRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE)) 602 { 603 goto unknowned; 604 } 605 606 break; 607 } 608 609 default: 610unknowned: 611 switch (ctrl->bmRequestType & USB_RECIP_MASK) 612 { 613 case USB_RECIP_INTERFACE: 614 case USB_RECIP_ENDPOINT: 615 (void)composite_classsetup(usb_cdev, dev, ctrl, dataout, outlen); 616 break; 617 618 default: 619 break; 620 } 621 goto success; 622 } 623 624 if (new_req) 625 { 626 value = EP_SUBMIT(dev->ep0, usb_req); 627 if (value < 0) 628 { 629 PRINT_ERR("endpoint send fail!\n"); 630 usb_req->result = 0; 631 return -1; 632 } 633 } 634 635success: 636 return value; 637} 638 639static void usb_composite_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 640{ 641 struct composite_dev_s *priv; 642 int i; 643 644 /* Extract reference to private data */ 645 646 priv = ((struct composite_driver_s *)driver)->dev; 647 if (priv == NULL) 648 { 649 return; 650 } 651 652 for (i = 0; i < priv->ndevices; i++) 653 { 654 CLASS_DISCONNECT(priv->device[i].dev, dev); 655 } 656} 657 658static void usb_composite_suspend(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 659{ 660 (void)driver; 661 (void)dev; 662 PRINT_WARN("%s is not support now!\n", __FUNCTION__); 663} 664 665static void usb_composite_resume(struct usbdevclass_driver_s *driver, struct usbdev_s *dev) 666{ 667 (void)driver; 668 (void)dev; 669 PRINT_WARN("%s is not support now!\n", __FUNCTION__); 670} 671 672static struct usbdevclass_driverops_s g_composite_driverops = 673{ 674 .bind = usb_composite_bind, /* bind */ 675 .unbind = usb_composite_unbind, /* unbind */ 676 .setup = usb_composite_setup, /* setup */ 677 .disconnect = usb_composite_disconnect, /* disconnect */ 678 .suspend = usb_composite_suspend, /* suspend */ 679 .resume = usb_composite_resume, /* resume */ 680}; 681 682/* probe composite device driver */ 683int usbd_composite_probe(struct composite_softc *cdev) 684{ 685 int ret; 686 687 if (cdev == NULL) 688 { 689 return -INVAL_ARGU; 690 } 691 692 /* probe and initiate device driver */ 693 ret = composite_device_init(cdev); 694 if (ret < 0) 695 { 696 PRINT_ERR("composite device init failed!, ret:%d\n", ret); 697 return -1; 698 } 699 700 return 0; 701} 702 703static int composite_probe(device_t dev) 704{ 705 return 0; 706} 707extern struct driver_module_data fcdcacm_simple_driver_mod; 708extern struct driver_module_data fconfig_simple_driver_mod; 709int composite_device_init(struct composite_softc *cdev) 710{ 711 int ret; 712#ifndef FCOFNIG_FUN 713 struct driver_module_data *mod = &fcdcacm_simple_driver_mod; 714#else 715 struct driver_module_data *mod = &fconfig_simple_driver_mod; 716#endif 717 if (mod->dmd_chainevh) 718 ret = mod->dmd_chainevh(NULL, MOD_LOAD, cdev); 719 return 0; 720} 721 722static int composite_attach(device_t dev) 723{ 724 struct composite_softc *usb_cdev = device_get_softc(dev); 725 void *parnet_conext = (void *)usb_cdev; 726 727 int ret; 728 729 if (usb_cdev == NULL || parnet_conext == NULL) 730 { 731 PRINT_ERR("%s usb_cdev or parnet_conext is null!\n", __FUNCTION__); 732 return -1; 733 } 734 735 /* probe gadget drivers */ 736 ret = usbd_composite_probe(usb_cdev); 737 if (ret < 0) 738 { 739 return -1; 740 } 741 742 usb_cdev->drvr.dev = &usb_cdev->dev; 743 usb_cdev->parnet_conext = parnet_conext; 744#ifndef FCOFNIG_FUN 745 usbd_start_udc(); 746 ret = usbd_gadget_attach_driver(parnet_conext, &usb_cdev->drvr.drvr); 747 if (ret < 0) 748 { 749 goto detach; 750 } 751#endif 752 DPRINTF("composite attach success!\n"); 753 return 0; /* Attach success */ 754#ifndef FCOFNIG_FUN 755detach: 756 (void)composite_detach(dev); 757 PRINT_ERR("%s failed, err=%d!\n", __FUNCTION__, ret); 758 return -1; /* No such device or address */ 759#endif 760} 761 762void composite_uninitialize(void *handle); 763static int composite_detach(device_t dev) 764{ 765 struct composite_softc *usb_cdev = device_get_softc(dev); 766 void *parnet_conext = device_get_softc(device_get_parent(dev)); 767 int ret; 768 769 if (usb_cdev == NULL || parnet_conext == NULL) 770 { 771 return -1; 772 } 773 PRINT_ERR("composite_detach!!!!!!!!!!!!!\n"); 774 sleep(1); 775 ret = usbd_gadget_detach_driver(parnet_conext, &usb_cdev->drvr.drvr); 776 if (ret != 0) 777 { 778 PRINT_ERR("%s failed, err=%d!\n", __FUNCTION__, ret); 779 return ret; 780 } 781 composite_uninitialize(usb_cdev); 782 783 DPRINTF("%s\n", __FUNCTION__); 784 return (0); 785} 786 787/**************************************************************************** 788 * Public Functions 789 ****************************************************************************/ 790/**************************************************************************** 791 * Name: composite_initialize 792 * 793 * Description: 794 * Register USB composite device as configured. This function will call 795 * board-specific implementations in order to obtain the class objects for 796 * each of the members of the composite. 797 * 798 * Input Parameters: 799 * None 800 * 801 * Returned Value: 802 * A non-NULL "handle" is returned on success. This handle may be used 803 * later with composite_uninitialize() in order to removed the composite 804 * device. This handle is the (untyped) internal representation of the 805 * the class driver instance. 806 * 807 * NULL is returned on any failure. 808 * 809 ****************************************************************************/ 810 811int composite_initialize(struct composite_softc *softc, uint8_t ndevices, 812 struct composite_devdesc_s *pdevices) 813{ 814 struct composite_dev_s *priv; 815 struct composite_driver_s *drvr; 816 int ret; 817 int i; 818 819 /* Convenience pointers into the allocated blob */ 820 821 priv = &softc->dev; 822 drvr = &softc->drvr; 823 824 /* Initialize the USB composite driver structure */ 825 826 (void)memset_s(priv, sizeof(struct composite_dev_s), 0, sizeof(struct composite_dev_s)); 827 priv->cfgdescsize = 0; 828 priv->ninterfaces = 0; 829 830 /* Get the constituent class driver objects */ 831 832 for (i = 0; i < ndevices; i++) 833 { 834 (void)memcpy_s(&priv->device[i].compdesc, sizeof(struct composite_devdesc_s), 835 &pdevices[i], sizeof(struct composite_devdesc_s)); 836 ret = priv->device[i].compdesc.classobject(priv->device[i].compdesc.minor, 837 &priv->device[i].compdesc.devinfo, 838 &priv->device[i].dev); 839 if (ret < 0) 840 { 841 return -1; 842 } 843 priv->cfgdescsize += priv->device[i].compdesc.cfgdescsize; 844 priv->ninterfaces += priv->device[i].compdesc.devinfo.ninterfaces; 845 } 846 priv->ndevices = ndevices; 847 848 /* Initialize the USB class driver structure */ 849 850 drvr->drvr.speed = USB_SPEED_HIGH; 851 drvr->drvr.ops = &g_composite_driverops; 852 drvr->dev = priv; 853 854 return 0; 855} 856 857void composite_uninitialize(void *handle) 858{ 859 struct composite_softc *usb_cdev = (struct composite_softc *)handle; 860 struct composite_dev_s *cdev = &usb_cdev->dev; 861 int i; 862 863 /* First phase uninitialization each of the member classes */ 864 865 for (i = 0; i < cdev->ndevices; i++) 866 { 867 cdev->device[i].compdesc.uninitialize(cdev->device[i].dev); 868 } 869} 870 871struct composite_devobj_s *usbclass_devobj_get(struct composite_dev_s *cdev, device_type type) 872{ 873 int i; 874 struct composite_devdesc_s *compdesc; 875 876 for (i = 0; i < NUM_DEVICES_TO_HANDLE; i++) 877 { 878 compdesc = &cdev->device[i].compdesc; 879 if (compdesc->minor == type) 880 { 881 return &cdev->device[i]; 882 } 883 } 884 885 return NULL; 886} 887 888#undef USB_DEBUG_VAR 889