1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * USB device layer File: usbd.c 5 * 6 * This module deals with devices (things connected to USB buses) 7 * 8 * Author: Mitch Lichtenberg (mpl@broadcom.com) 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 15 * This software is furnished under license and may be used and 16 * copied only in accordance with the following terms and 17 * conditions. Subject to these conditions, you may download, 18 * copy, install, use, modify and distribute modified or unmodified 19 * copies of this software in source and/or binary form. No title 20 * or ownership is transferred hereby. 21 * 22 * 1) Any source code used, modified or distributed must reproduce 23 * and retain this copyright notice and list of conditions 24 * as they appear in the source file. 25 * 26 * 2) No right is granted to use any trade name, trademark, or 27 * logo of Broadcom Corporation. The "Broadcom Corporation" 28 * name may not be used to endorse or promote products derived 29 * from this software without the prior written permission of 30 * Broadcom Corporation. 31 * 32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 44 * THE POSSIBILITY OF SUCH DAMAGE. 45 ********************************************************************* */ 46 47 48#ifndef _CFE_ 49#include <stdio.h> 50#include <time.h> 51#include <memory.h> 52#include <stdint.h> 53#include "usbhack.h" 54#else 55#include "lib_types.h" 56#include "lib_string.h" 57#include "lib_printf.h" 58#include "cfe_timer.h" 59#endif 60 61#include "lib_malloc.h" 62#include "lib_queue.h" 63#include "usbchap9.h" 64#include "usbd.h" 65 66/* ********************************************************************* 67 * Globals 68 ********************************************************************* */ 69 70int usb_noisy = 0; 71 72 73/* ********************************************************************* 74 * usb_create_pipe(dev,epaddr,mps,flags) 75 * 76 * Create a pipe, causing the corresponding endpoint to 77 * be created in the host controller driver. Pipes form the 78 * basic "handle" for unidirectional communications with a 79 * USB device. 80 * 81 * Input parameters: 82 * dev - device we're talking about 83 * epaddr - endpoint address open, usually from the endpoint 84 * descriptor 85 * mps - maximum packet size understood by the device 86 * flags - flags for this pipe (UP_xxx flags) 87 * 88 * Return value: 89 * <0 if error 90 * 0 if ok 91 ********************************************************************* */ 92 93int usb_create_pipe(usbdev_t *dev,int epaddr,int mps,int flags) 94{ 95 usbpipe_t *pipe; 96 int pipeidx; 97 98 pipeidx = USB_EPADDR_TO_IDX(epaddr); 99 100 if (dev->ud_pipes[pipeidx] != NULL) { 101 printf("Trying to create a pipe that was already created!\n"); 102 return 0; 103 } 104 105 pipe = KMALLOC(sizeof(usbpipe_t),0); 106 107 if (!pipe) return -1; 108 109 pipe->up_flags = flags; 110 pipe->up_num = pipeidx; 111 pipe->up_mps = mps; 112 pipe->up_dev = dev; 113 if (dev->ud_flags & UD_FLAG_LOWSPEED) flags |= UP_TYPE_LOWSPEED; 114 pipe->up_hwendpoint = UBEPTCREATE(dev->ud_bus, 115 dev->ud_address, 116 USB_ENDPOINT_ADDRESS(epaddr), 117 mps, 118 flags); 119 120 dev->ud_pipes[pipeidx] = pipe; 121 122 return 0; 123} 124 125/* ********************************************************************* 126 * usb_open_pipe(dev,epdesc) 127 * 128 * Open a pipe given an endpoint descriptor - this is the 129 * normal way pipes get open, since you've just selected a 130 * configuration and have the descriptors handy with all 131 * the information you need. 132 * 133 * Input parameters: 134 * dev - device we're talking to 135 * epdesc - endpoint descriptor 136 * 137 * Return value: 138 * <0 if error 139 * else endpoint/pipe number (from descriptor) 140 ********************************************************************* */ 141 142int usb_open_pipe(usbdev_t *dev,usb_endpoint_descr_t *epdesc) 143{ 144 int res; 145 int flags = 0; 146 147 if (USB_ENDPOINT_DIR_IN(epdesc->bEndpointAddress)) flags |= UP_TYPE_IN; 148 else flags |= UP_TYPE_OUT; 149 150 switch (epdesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) { 151 case USB_ENDPOINT_TYPE_CONTROL: 152 flags |= UP_TYPE_CONTROL; 153 break; 154 case USB_ENDPOINT_TYPE_ISOCHRONOUS: 155 flags |= UP_TYPE_ISOC; 156 break; 157 case USB_ENDPOINT_TYPE_BULK: 158 flags |= UP_TYPE_BULK; 159 break; 160 case USB_ENDPOINT_TYPE_INTERRUPT: 161 flags |= UP_TYPE_INTR; 162 break; 163 } 164 165 res = usb_create_pipe(dev, 166 epdesc->bEndpointAddress, 167 GETUSBFIELD(epdesc,wMaxPacketSize), 168 flags); 169 170 if (res < 0) return res; 171 172 return epdesc->bEndpointAddress; 173} 174 175 176/* ********************************************************************* 177 * usb_destroy_pipe(dev,epaddr) 178 * 179 * Close(destroy) an open pipe and remove endpoint descriptor 180 * 181 * Input parameters: 182 * dev - device we're talking to 183 * epaddr - pipe to close 184 * 185 * Return value: 186 * nothing 187 ********************************************************************* */ 188 189void usb_destroy_pipe(usbdev_t *dev,int epaddr) 190{ 191 usbpipe_t *pipe; 192 int pipeidx; 193 194 pipeidx = USB_EPADDR_TO_IDX(epaddr); 195 196 pipe = dev->ud_pipes[pipeidx]; 197 if (!pipe) return; 198 199 if (dev->ud_pipes[pipeidx]) { 200 UBEPTDELETE(dev->ud_bus, 201 dev->ud_pipes[pipeidx]->up_hwendpoint); 202 } 203 204 KFREE(dev->ud_pipes[pipeidx]); 205 dev->ud_pipes[pipeidx] = NULL; 206} 207 208/* ********************************************************************* 209 * usb_destroy_device(dev) 210 * 211 * Delete an entire USB device, closing its pipes and freeing 212 * the device data structure 213 * 214 * Input parameters: 215 * dev - device to destroy 216 * 217 * Return value: 218 * nothing 219 ********************************************************************* */ 220 221void usb_destroy_device(usbdev_t *dev) 222{ 223 int idx; 224 225 for (idx = 0; idx < UD_MAX_PIPES; idx++) { 226 if (dev->ud_pipes[idx]) { 227 UBEPTDELETE(dev->ud_bus, 228 dev->ud_pipes[idx]->up_hwendpoint); 229 KFREE(dev->ud_pipes[idx]); 230 } 231 } 232 233 dev->ud_bus->ub_devices[dev->ud_address] = NULL; 234 235 KFREE(dev); 236} 237 238 239/* ********************************************************************* 240 * usb_create_device(bus,lowspeed) 241 * 242 * Create a new USB device. This device will be set to 243 * communicate on address zero (default address) and will be 244 * ready for basic stuff so we can figure out what it is. 245 * The control pipe will be open, so you can start requesting 246 * descriptors right away. 247 * 248 * Input parameters: 249 * bus - bus to create device on 250 * lowspeed - true if it's a lowspeed device (the hubs tell 251 * us these things) 252 * 253 * Return value: 254 * usb device structure, or NULL 255 ********************************************************************* */ 256 257usbdev_t *usb_create_device(usbbus_t *bus,int lowspeed) 258{ 259 usbdev_t *dev; 260 int pipeflags; 261 262 /* 263 * Create the device structure. 264 */ 265 266 dev = KMALLOC(sizeof(usbdev_t),0); 267 memset(dev,0,sizeof(usbdev_t)); 268 269 dev->ud_bus = bus; 270 dev->ud_address = 0; /* default address */ 271 dev->ud_parent = NULL; 272 dev->ud_flags = 0; 273 274 /* 275 * Adjust things based on the target device speed 276 */ 277 278 pipeflags = UP_TYPE_CONTROL; 279 if (lowspeed) { 280 pipeflags |= UP_TYPE_LOWSPEED; 281 dev->ud_flags |= UD_FLAG_LOWSPEED; 282 } 283 284 /* 285 * Create the control pipe. 286 */ 287 288 usb_create_pipe(dev,0, 289 USB_CONTROL_ENDPOINT_MIN_SIZE, 290 pipeflags); 291 292 return dev; 293} 294 295/* ********************************************************************* 296 * usb_make_request(dev,epaddr,buf,len,flags) 297 * 298 * Create a template request structure with basic fields 299 * ready to go. A shorthand routine. 300 * 301 * Input parameters: 302 * dev- device we're talking to 303 * epaddr - endpoint address, from usb_open_pipe() 304 * buf,length - user buffer and buffer length 305 * flags - transfer direction, etc. (UR_xxx flags) 306 * 307 * Return value: 308 * usbreq_t pointer, or NULL 309 ********************************************************************* */ 310 311usbreq_t *usb_make_request(usbdev_t *dev,int epaddr,uint8_t *buf,int length,int flags) 312{ 313 usbreq_t *ur; 314 usbpipe_t *pipe; 315 int pipeidx; 316 317 pipeidx = USB_EPADDR_TO_IDX(epaddr); 318 319 pipe = dev->ud_pipes[pipeidx]; 320 321 if (pipe == NULL) return NULL; 322 323 ur = KMALLOC(sizeof(usbreq_t),0); 324 memset(ur,0,sizeof(usbreq_t)); 325 326 ur->ur_dev = dev; 327 ur->ur_pipe = pipe; 328 ur->ur_buffer = buf; 329 ur->ur_length = length; 330 ur->ur_flags = flags; 331 ur->ur_callback = NULL; 332 333 return ur; 334 335} 336 337/* ********************************************************************* 338 * usb_poll(bus) 339 * 340 * Handle device-driver polling - simply vectors to host controller 341 * driver. 342 * 343 * Input parameters: 344 * bus - bus structure 345 * 346 * Return value: 347 * nothing 348 ********************************************************************* */ 349 350void usb_poll(usbbus_t *bus) 351{ 352 UBINTR(bus); 353} 354 355/* ********************************************************************* 356 * usb_daemon(bus) 357 * 358 * Polls for topology changes and initiates a bus scan if 359 * necessary. 360 * 361 * Input parameters: 362 * bus - bus to watch 363 * 364 * Return value: 365 * nothing 366 ********************************************************************* */ 367 368void usb_daemon(usbbus_t *bus) 369{ 370 /* 371 * Just see if someone flagged a need for a scan here 372 * and start the bus scan if necessary. 373 * 374 * The actual scanning is a hub function, starting at the 375 * root hub, so the code for that is over there. 376 */ 377 378 if (bus->ub_flags & UB_FLG_NEEDSCAN) { 379 bus->ub_flags &= ~UB_FLG_NEEDSCAN; 380 usb_scan(bus); 381 } 382} 383 384/* ********************************************************************* 385 * usb_cancel_request(ur) 386 * 387 * Cancel a pending usb transfer request. 388 * 389 * Input parameters: 390 * ur - request to cancel 391 * 392 * Return value: 393 * 0 if ok 394 * else error (could not find request) 395 ********************************************************************* */ 396 397int usb_cancel_request(usbreq_t *ur) 398{ 399 printf("usb_cancel_request is not implemented.\n"); 400 return 0; 401} 402 403/* ********************************************************************* 404 * usb_free_request(ur) 405 * 406 * Return a transfer request to the free pool. 407 * 408 * Input parameters: 409 * ur - request to return 410 * 411 * Return value: 412 * nothing 413 ********************************************************************* */ 414 415void usb_free_request(usbreq_t *ur) 416{ 417 if (ur->ur_inprogress) { 418 printf("Yow! Tried to free a request that was in progress!\n"); 419 return; 420 } 421 KFREE(ur); 422} 423 424/* ********************************************************************* 425 * usb_delay_ms(bus,ms) 426 * 427 * Wait a while, calling the polling routine as we go. 428 * 429 * Input parameters: 430 * bus - bus we're talking to 431 * ms - how long to wait 432 * 433 * Return value: 434 * nothing 435 ********************************************************************* */ 436 437 438void usb_delay_ms(usbbus_t *bus,int ms) 439{ 440#ifdef _CFE_ 441 cfe_sleep(1+((ms*CFE_HZ)/1000)); 442#else 443 mydelay(ms); 444#endif 445} 446 447/* ********************************************************************* 448 * usb_queue_request(ur) 449 * 450 * Call the transfer handler in the host controller driver to 451 * set up a transfer descriptor 452 * 453 * Input parameters: 454 * ur - request to queue 455 * 456 * Return value: 457 * 0 if ok 458 * else error 459 ********************************************************************* */ 460 461int usb_queue_request(usbreq_t *ur) 462{ 463 int res; 464 465 ur->ur_inprogress = 1; 466 ur->ur_xferred = 0; 467 res = UBXFER(ur->ur_dev->ud_bus, 468 ur->ur_pipe->up_hwendpoint, 469 ur); 470 return res; 471} 472 473/* ********************************************************************* 474 * usb_wait_request(ur) 475 * 476 * Wait until a request completes, calling the polling routine 477 * as we wait. 478 * 479 * Input parameters: 480 * ur - request to wait for 481 * 482 * Return value: 483 * request status 484 ********************************************************************* */ 485 486int usb_wait_request(usbreq_t *ur) 487{ 488 while ((volatile int) (ur->ur_inprogress)) { 489 usb_poll(ur->ur_dev->ud_bus); 490 } 491 492 return ur->ur_status; 493} 494 495/* ********************************************************************* 496 * usb_sync_request(ur) 497 * 498 * Synchronous request - call usb_queue and then usb_wait 499 * 500 * Input parameters: 501 * ur - request to submit 502 * 503 * Return value: 504 * status of request 505 ********************************************************************* */ 506 507int usb_sync_request(usbreq_t *ur) 508{ 509 usb_queue_request(ur); 510 return usb_wait_request(ur); 511} 512 513/* ********************************************************************* 514 * usb_simple_request(dev,reqtype,bRequest,wValue,wIndex) 515 * 516 * Handle a simple USB control pipe request. These are OUT 517 * requests with no data phase. 518 * 519 * Input parameters: 520 * dev - device we're talking to 521 * reqtype - request type (bmRequestType) for descriptor 522 * wValue - wValue for descriptor 523 * wIndex - wIndex for descriptor 524 * 525 * Return value: 526 * 0 if ok 527 * else error 528 ********************************************************************* */ 529 530int usb_simple_request(usbdev_t *dev,uint8_t reqtype,int bRequest,int wValue,int wIndex) 531{ 532 return usb_std_request(dev,reqtype,bRequest,wValue,wIndex,NULL,0); 533 534} 535 536 537/* ********************************************************************* 538 * usb_set_configuration(dev,config) 539 * 540 * Set the current configuration for a USB device. 541 * 542 * Input parameters: 543 * dev - device we're talking to 544 * config - bConfigValue for the device 545 * 546 * Return value: 547 * request status 548 ********************************************************************* */ 549 550int usb_set_configuration(usbdev_t *dev,int config) 551{ 552 int res; 553 554 res = usb_simple_request(dev,0x00,USB_REQUEST_SET_CONFIGURATION,config,0); 555 556 return res; 557} 558 559 560/* ********************************************************************* 561 * usb_new_address(bus) 562 * 563 * Return the next available address for the specified bus 564 * 565 * Input parameters: 566 * bus - bus to assign an address for 567 * 568 * Return value: 569 * new address, <0 if error 570 ********************************************************************* */ 571 572int usb_new_address(usbbus_t *bus) 573{ 574 int idx; 575 576 for (idx = 1; idx < USB_MAX_DEVICES; idx++) { 577 if (bus->ub_devices[idx] == NULL) return idx; 578 } 579 580 return -1; 581} 582 583/* ********************************************************************* 584 * usb_set_address(dev,address) 585 * 586 * Set the address of a device. This also puts the device 587 * in the master device table for the bus and reconfigures the 588 * address of the control pipe. 589 * 590 * Input parameters: 591 * dev - device we're talking to 592 * address - new address (1..127) 593 * 594 * Return value: 595 * request status 596 ********************************************************************* */ 597 598int usb_set_address(usbdev_t *dev,int address) 599{ 600 int res; 601 int idx; 602 usbpipe_t *pipe; 603 604 res = usb_simple_request(dev,0x00,USB_REQUEST_SET_ADDRESS,address,0); 605 606 if (res == 0) { 607 dev->ud_bus->ub_devices[address] = dev; 608 dev->ud_address = address; 609 for (idx = 0; idx < UD_MAX_PIPES; idx++) { 610 pipe = dev->ud_pipes[idx]; 611 if (pipe && pipe->up_hwendpoint) { 612 UBEPTSETADDR(dev->ud_bus,pipe->up_hwendpoint,address); 613 } 614 } 615 } 616 617 return res; 618} 619 620/* ********************************************************************* 621 * usb_set_ep0mps(dev,mps) 622 * 623 * Set the maximum packet size of endpoint zero (mucks with the 624 * endpoint in the host controller) 625 * 626 * Input parameters: 627 * dev - device we're talking to 628 * mps - max packet size for endpoint zero 629 * 630 * Return value: 631 * request status 632 ********************************************************************* */ 633 634int usb_set_ep0mps(usbdev_t *dev,int mps) 635{ 636 usbpipe_t *pipe; 637 638 pipe = dev->ud_pipes[0]; 639 if (pipe && pipe->up_hwendpoint) { 640 UBEPTSETMPS(dev->ud_bus,pipe->up_hwendpoint,mps); 641 } 642 if (pipe) { 643 pipe->up_mps = mps; 644 } 645 646 return 0; 647} 648 649/* ********************************************************************* 650 * usb_clear_stall(dev,epaddr) 651 * 652 * Clear a stall condition on the specified pipe 653 * 654 * Input parameters: 655 * dev - device we're talking to 656 * epaddr - endpoint address 657 * 658 * Return value: 659 * 0 if ok 660 * else error 661 ********************************************************************* */ 662int usb_clear_stall(usbdev_t *dev,int epaddr) 663{ 664 uint8_t *requestbuf; 665 usb_device_request_t *req; 666 usbreq_t *ur; 667 int res; 668 int pipeidx; 669 670 /* 671 * Clear the stall in the hardware. 672 */ 673 674 pipeidx = USB_EPADDR_TO_IDX(epaddr); 675 676 UBEPTCLEARTOGGLE(dev->ud_bus,dev->ud_pipes[pipeidx]->up_hwendpoint); 677 678 /* 679 * Do the "clear stall" request. Note that we should do this 680 * without calling usb_simple_request, since usb_simple_request 681 * may itself stall. 682 */ 683 684 requestbuf = KMALLOC(32,0); 685 686 req = (usb_device_request_t *) requestbuf; 687 688 req->bmRequestType = 0x02; 689 req->bRequest = USB_REQUEST_CLEAR_FEATURE; 690 PUTUSBFIELD(req,wValue,0); /* ENDPOINT_HALT */ 691 PUTUSBFIELD(req,wIndex,epaddr); 692 PUTUSBFIELD(req,wLength,0); 693 694 ur = usb_make_request(dev,0,requestbuf, 695 sizeof(usb_device_request_t), 696 UR_FLAG_SETUP); 697 res = usb_sync_request(ur); 698 usb_free_request(ur); 699 ur = usb_make_request(dev,0,requestbuf,0,UR_FLAG_STATUS_IN); 700 res = usb_sync_request(ur); 701 usb_free_request(ur); 702 703 KFREE(requestbuf); 704 705 return 0; 706} 707 708 709 710/* ********************************************************************* 711 * usb_std_request(dev,bmRequestType,bRequest,wValue, 712 * wIndex,buffer,length) 713 * 714 * Do a standard control request on the control pipe, 715 * with the appropriate setup, data, and status phases. 716 * 717 * Input parameters: 718 * dev - dev we're talking to 719 * bmRequestType,bRequest,wValue,wIndex - fields for the 720 * USB request structure 721 * buffer - user buffer 722 * length - length of user buffer 723 * 724 * Return value: 725 * number of bytes transferred 726 ********************************************************************* */ 727 728int usb_std_request(usbdev_t *dev,uint8_t bmRequestType, 729 uint8_t bRequest,uint16_t wValue, 730 uint16_t wIndex,uint8_t *buffer,int length) 731{ 732 usbpipe_t *pipe = dev->ud_pipes[0]; 733 usbreq_t *ur; 734 int res; 735 usb_device_request_t *req; 736 uint8_t *databuf = NULL; 737 738 req = KMALLOC(32,0); 739 740 if ((buffer != NULL) && (length !=0)) { 741 databuf = KMALLOC(length,0); 742 if (!(bmRequestType & USBREQ_DIR_IN)) { 743 memcpy(databuf,buffer,length); 744 } 745 else { 746 memset(databuf,0,length); 747 } 748 } 749 750 req->bmRequestType = bmRequestType; 751 req->bRequest = bRequest; 752 PUTUSBFIELD(req,wValue,wValue); 753 PUTUSBFIELD(req,wIndex,wIndex); 754 PUTUSBFIELD(req,wLength,length); 755 756 ur = usb_make_request(dev,0,(uint8_t *)req,sizeof(usb_device_request_t),UR_FLAG_SETUP); 757 res = usb_sync_request(ur); 758 usb_free_request(ur); 759 760 if (length != 0) { 761 if (bmRequestType & USBREQ_DIR_IN) { 762 ur = usb_make_request(dev,0,databuf,length,UR_FLAG_IN); 763 } 764 else { 765 ur = usb_make_request(dev,0,databuf,length,UR_FLAG_OUT); 766 } 767 768 res = usb_sync_request(ur); 769 770 if (res == 4) { /* STALL */ 771 usb_clear_stall(dev,pipe->up_num); 772 usb_free_request(ur); 773 if (databuf) KFREE(databuf); 774 KFREE(req); 775 return 0; 776 } 777 778 length = ur->ur_xferred; 779 usb_free_request(ur); 780 } 781 782 if ((length != 0) && (databuf != NULL) && (bmRequestType & USBREQ_DIR_IN)) { 783 memcpy(buffer,databuf,length); 784 } 785 786 if (bmRequestType & USBREQ_DIR_IN) { 787 ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_OUT); 788 } 789 else { 790 ur = usb_make_request(dev,0,(uint8_t *)req,0,UR_FLAG_STATUS_IN); 791 } 792 793 res = usb_sync_request(ur); 794 usb_free_request(ur); 795 796 if (res == 4) { /* STALL */ 797 usb_clear_stall(dev,pipe->up_num); 798 if (databuf) KFREE(databuf); 799 KFREE(req); 800 return 0; 801 } 802 803 if (databuf) KFREE(databuf); 804 KFREE(req); 805 806 return length; 807} 808 809 810 811 812/* ********************************************************************* 813 * usb_get_descriptor(dev,reqtype,dsctype,dscidx,respbuf,buflen) 814 * 815 * Request a descriptor from the device. 816 * 817 * Input parameters: 818 * dev - device we're talking to 819 * reqtype - bmRequestType field for descriptor we want 820 * dsctype - descriptor type we want 821 * dscidx - index of descriptor we want (often zero) 822 * respbuf - response buffer 823 * buflen - length of response buffer 824 * 825 * Return value: 826 * number of bytes transferred 827 ********************************************************************* */ 828 829int usb_get_descriptor(usbdev_t *dev,uint8_t reqtype,int dsctype,int dscidx, 830 uint8_t *respbuf,int buflen) 831{ 832 return usb_std_request(dev, 833 reqtype,USB_REQUEST_GET_DESCRIPTOR, 834 USB_DESCRIPTOR_TYPEINDEX(dsctype,dscidx), 835 0, 836 respbuf,buflen); 837} 838 839/* ********************************************************************* 840 * usb_get_string(dev,id,buf,maxlen) 841 * 842 * Request a string from the device, converting it from 843 * unicode to ascii (brutally). 844 * 845 * Input parameters: 846 * dev - device we're talking to 847 * id - string ID 848 * buf - buffer to receive string (null terminated) 849 * maxlen - length of buffer 850 * 851 * Return value: 852 * number of characters in returned string 853 ********************************************************************* */ 854 855int usb_get_string(usbdev_t *dev,int id,char *buf,int maxlen) 856{ 857 int amtcopy; 858 uint8_t *respbuf; 859 int idx; 860 usb_string_descr_t *sdscr; 861 862 respbuf = KMALLOC(maxlen*2+2,0); 863 sdscr = (usb_string_descr_t *) respbuf; 864 865 /* 866 * First time just get the header of the descriptor so we can 867 * get the string length 868 */ 869 870 amtcopy = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_STRING_DESCRIPTOR_TYPE,id, 871 respbuf,2); 872 873 /* 874 * now do it again to get the whole string. 875 */ 876 877 if (maxlen > sdscr->bLength) maxlen = sdscr->bLength; 878 879 amtcopy = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_STRING_DESCRIPTOR_TYPE,id, 880 respbuf,maxlen); 881 882 *buf = '\0'; 883 amtcopy = sdscr->bLength - 2; 884 if (amtcopy <= 0) return amtcopy; 885 886 for (idx = 0; idx < amtcopy; idx+=2) { 887 *buf++ = sdscr->bString[idx]; 888 } 889 890 *buf = '\0'; 891 892 KFREE(respbuf); 893 894 return amtcopy; 895} 896 897 898 899/* ********************************************************************* 900 * usb_get_device_descriptor(dev,dscr,smallflg) 901 * 902 * Request the device descriptor for the device. This is often 903 * the first descriptor requested, so it needs to be done in 904 * stages so we can find out how big the control pipe is. 905 * 906 * Input parameters: 907 * dev - device we're talking to 908 * dscr - pointer to buffer to receive descriptor 909 * smallflg - TRUE to request just 8 bytes. 910 * 911 * Return value: 912 * number of bytes copied 913 ********************************************************************* */ 914 915int usb_get_device_descriptor(usbdev_t *dev,usb_device_descr_t *dscr,int smallflg) 916{ 917 int res; 918 uint8_t *respbuf; 919 int amtcopy; 920 921 /* 922 * Smallflg truncates the request 8 bytes. We need to do this for 923 * the very first transaction to a USB device in order to determine 924 * the size of its control pipe. Bad things will happen if you 925 * try to retrieve more data than the control pipe will hold. 926 * 927 * So, be conservative at first and get the first 8 bytes of the 928 * descriptor. Byte 7 is bMaxPacketSize0, the size of the control 929 * pipe. Then you can go back and submit a bigger request for 930 * everything else. 931 */ 932 933 amtcopy = smallflg ? USB_CONTROL_ENDPOINT_MIN_SIZE : sizeof(usb_device_descr_t); 934 935 respbuf = KMALLOC(64,0); 936 res = usb_get_descriptor(dev,USBREQ_DIR_IN,USB_DEVICE_DESCRIPTOR_TYPE,0,respbuf,amtcopy); 937 memcpy(dscr,respbuf,amtcopy); 938 KFREE(respbuf); 939 return res; 940 941} 942 943/* ********************************************************************* 944 * usb_get_config_descriptor(dev,dscr,idx,maxlen) 945 * 946 * Request the configuration descriptor from the device. 947 * 948 * Input parameters: 949 * dev - device we're talking to 950 * dscr - descriptor buffer (receives data from device) 951 * idx - index of config we want (usually zero) 952 * maxlen - total size of buffer to receive descriptor 953 * 954 * Return value: 955 * number of bytes copied 956 ********************************************************************* */ 957 958int usb_get_config_descriptor(usbdev_t *dev,usb_config_descr_t *dscr,int idx,int maxlen) 959{ 960 int res; 961 uint8_t *respbuf; 962 963 respbuf = KMALLOC(maxlen,0); 964 res = usb_get_descriptor(dev,USBREQ_DIR_IN, 965 USB_CONFIGURATION_DESCRIPTOR_TYPE,idx, 966 respbuf,maxlen); 967 memcpy(dscr,respbuf,maxlen); 968 KFREE(respbuf); 969 return res; 970 971} 972 973 974 975/* ********************************************************************* 976 * usb_get_device_status(dev,status) 977 * 978 * Request status from the device (status descriptor) 979 * 980 * Input parameters: 981 * dev - device we're talking to 982 * status - receives device_status structure 983 * 984 * Return value: 985 * number of bytes returned 986 ********************************************************************* */ 987 988int usb_get_device_status(usbdev_t *dev,usb_device_status_t *status) 989{ 990 return usb_std_request(dev, 991 USBREQ_DIR_IN, 992 0, 993 0, 994 0, 995 (uint8_t *) status, 996 sizeof(usb_device_status_t)); 997} 998 999 1000/* ********************************************************************* 1001 * usb_complete_request(ur,status) 1002 * 1003 * Called when a usb request completes - pass status to 1004 * caller and call the callback if there is one. 1005 * 1006 * Input parameters: 1007 * ur - usbreq_t to complete 1008 * status - completion status 1009 * 1010 * Return value: 1011 * nothing 1012 ********************************************************************* */ 1013 1014void usb_complete_request(usbreq_t *ur,int status) 1015{ 1016 ur->ur_status = status; 1017 ur->ur_inprogress = 0; 1018 if (ur->ur_callback) (*(ur->ur_callback))(ur); 1019} 1020 1021 1022/* ********************************************************************* 1023 * usb_initroot(bus) 1024 * 1025 * Initialize the root hub for the bus - we need to do this 1026 * each time a bus is configured. 1027 * 1028 * Input parameters: 1029 * bus - bus to initialize 1030 * 1031 * Return value: 1032 * nothing 1033 ********************************************************************* */ 1034 1035void usb_initroot(usbbus_t *bus) 1036{ 1037 usbdev_t *dev; 1038 usb_driver_t *drv; 1039 int addr; 1040 int res; 1041 uint8_t *buf; 1042 int len; 1043 usb_config_descr_t cfgdescr; 1044 1045 /* 1046 * Create a device for the root hub. 1047 */ 1048 1049 dev = usb_create_device(bus,0); 1050 bus->ub_roothub = dev; 1051 1052 /* 1053 * Get the device descriptor. Make sure it's a hub. 1054 */ 1055 1056 res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),TRUE); 1057 1058 if (dev->ud_devdescr.bDeviceClass != USB_DEVICE_CLASS_HUB) { 1059 printf("Error! Root device is not a hub!\n"); 1060 return; 1061 } 1062 1063 /* 1064 * Set up the max packet size for the control endpoint, 1065 * then get the rest of the descriptor. 1066 */ 1067 1068 usb_set_ep0mps(dev,dev->ud_devdescr.bMaxPacketSize0); 1069 res = usb_get_device_descriptor(dev,&(dev->ud_devdescr),FALSE); 1070 1071 /* 1072 * Obtain a new address and set the address of the 1073 * root hub to this address. 1074 */ 1075 1076 addr = usb_new_address(dev->ud_bus); 1077 res = usb_set_address(dev,addr); 1078 1079 /* 1080 * Get the configuration descriptor and all the 1081 * associated interface and endpoint descriptors. 1082 */ 1083 1084 res = usb_get_config_descriptor(dev,&cfgdescr,0, 1085 sizeof(usb_config_descr_t)); 1086 if (res != sizeof(usb_config_descr_t)) { 1087 printf("[a]usb_get_config_descriptor returns %d\n",res); 1088 } 1089 1090 len = GETUSBFIELD(&cfgdescr,wTotalLength); 1091 buf = KMALLOC(len,0); 1092 1093 res = usb_get_config_descriptor(dev,(usb_config_descr_t *)buf,0,len); 1094 if (res != len) { 1095 printf("[b]usb_get_config_descriptor returns %d\n",res); 1096 } 1097 1098 dev->ud_cfgdescr = (usb_config_descr_t *) buf; 1099 1100 /* 1101 * Select the configuration. Not really needed for our poor 1102 * imitation root hub, but it's the right thing to do. 1103 */ 1104 1105 usb_set_configuration(dev,cfgdescr.bConfigurationValue); 1106 1107 /* 1108 * Find the driver for this. It had better be the hub 1109 * driver. 1110 */ 1111 1112 drv = usb_find_driver(dev); 1113 1114 /* 1115 * Call the attach method. 1116 */ 1117 1118 (*(drv->udrv_attach))(dev,drv); 1119 1120 /* 1121 * Hub should now be operational. 1122 */ 1123 1124} 1125 1126 1127/* ********************************************************************* 1128 * usb_find_cfg_descr(dev,dtype,idx) 1129 * 1130 * Find a configuration descriptor - we retrieved all the config 1131 * descriptors during discovery, this lets us dig out the one 1132 * we want. 1133 * 1134 * Input parameters: 1135 * dev - device we are talking to 1136 * dtype - descriptor type to find 1137 * idx - index of descriptor if there's more than one 1138 * 1139 * Return value: 1140 * pointer to descriptor or NULL if not found 1141 ********************************************************************* */ 1142 1143void *usb_find_cfg_descr(usbdev_t *dev,int dtype,int idx) 1144{ 1145 uint8_t *endptr; 1146 uint8_t *ptr; 1147 usb_config_descr_t *cfgdscr; 1148 1149 if (dev->ud_cfgdescr == NULL) return NULL; 1150 1151 ptr = (uint8_t *) dev->ud_cfgdescr; 1152 endptr = ptr + GETUSBFIELD((dev->ud_cfgdescr),wTotalLength); 1153 1154 while (ptr < endptr) { 1155 1156 cfgdscr = (usb_config_descr_t *) ptr; 1157 1158 if (cfgdscr->bDescriptorType == dtype) { 1159 if (idx == 0) return (void *) ptr; 1160 else idx--; 1161 } 1162 1163 ptr += cfgdscr->bLength; 1164 1165 } 1166 1167 return NULL; 1168} 1169