1.\" $NetBSD: usbnet.9,v 1.17 2022/03/05 06:55:58 riastradh Exp $ 2.\" 3.\" Copyright (c) 2019 Matthew R. Green 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25.\" SUCH DAMAGE. 26.\" 27.Dd March 15, 2020 28.Dt USBNET 9 29.Os 30.Sh NAME 31.Nm usbnet 32.Nd common USB Ethernet driver framework 33.Sh SYNOPSIS 34.In dev/usb/usbnet.h 35.Ss Functions offered by usbnet.h 36.Ft void 37.Fn usbnet_set_link "struct usbnet *un" "bool link" 38.Ft struct ifnet * 39.Fn usbnet_ifp "struct usbnet *un" 40.Ft struct ethercom * 41.Fn usbnet_ec "struct usbnet *un" 42.Ft struct mii_data * 43.Fn usbnet_mii "struct usbnet *un" 44.Ft krndsource_t * 45.Fn usbnet_rndsrc "struct usbnet *un" 46.Ft void * 47.Fn usbnet_softc "struct usbnet *un" 48.Ft bool 49.Fn usbnet_havelink "struct usbnet *un" 50.Ft bool 51.Fn usbnet_isdying "struct usbnet *un" 52.Ft void 53.Fn usbnet_enqueue "struct usbnet *un" "uint8_t *buf" "size_t buflen" "int csum_flags" "uint32_t csum_data" "int mbuf_flags" 54.Ft void 55.Fn usbnet_input "struct usbnet *un" "uint8_t *buf" "size_t buflen" 56.Ft void 57.Fn usbnet_attach "struct usbnet *un" 58.Ft void 59.Fn usbnet_attach_ifp "struct usbnet *un" "unsigned if_flags" "unsigned if_extflags" "const struct usbnet_mii *unm" 60.Ft int 61.Fn usbnet_detach "device_t dev" "int flags" 62.Ft int 63.Fn usbnet_activate "device_t dev" "devact_t act" 64.Sh DESCRIPTION 65The 66.Nm 67framework provides methods usable for USB Ethernet drivers. 68The framework has support for these features: 69.Bl -bullet -offset 8n 70.It 71Partial autoconf handling 72.It 73USB endpoint pipe handling 74.It 75Rx and Tx chain handling 76.It 77Generic handlers or support for several struct ifnet callbacks 78.It 79Network stack locking protocol 80.It 81Interrupt handling 82.El 83.Pp 84.Nm 85provides many or all of the traditional 86.Dq softc 87members inside 88.Va struct usbnet , 89which can be used directly as the device softc structure if 90no additional storage is required. 91A structure exists for receive and transmit chain management, 92.Va struct usbnet_chain , 93that tracks the metadata for each transfer descriptor available, 94minimum of one each for Rx and Tx slot, and will be passed 95to the Rx and Tx callbacks. 96.Pp 97There is a 98.Va struct usbnet_ops 99structure that provides a number of optional and required callbacks 100that will be described below. 101.Pp 102For autoconfiguration the device attach routine is expected to 103ensure that this device's 104.Va struct usbnet 105is the first member of the device softc, if it can not be used directly 106as the device softc, as well as set up the necessary structure members, 107find end-points, find the Ethernet address if relevant, call 108.Fn usbnet_attach , 109set up interface, Ethernet, and MII capabilities, and finally call 110.Fn usbnet_attach_ifp . 111The device detach routine should free any resources allocated 112by attach and then call 113.Fn usbnet_detach , 114possibly directly using 115.Fn usbnet_detach 116as most consumers have no additional resources not owned and 117released by the 118.Nm 119framework itself. 120The device activate function should be set to 121.Fn usbnet_activate . 122.Pp 123When bringing an interface up from 124.Xr if_init 9 , 125which happens under 126.Xr IFNET_LOCK 9 , 127.Nm 128will: 129.Bl -enum 130.It 131call 132.Dq uno_init 133to initialize the hardware for sending and receiving packets, 134.It 135open the USB pipes, 136.It 137allocate Rx and Tx buffers for transfers, 138.It 139call 140.Dq uno_mcast 141to initially program the hardware multicast filter, and finally 142.It 143start the Rx transfers so packets can be received. 144.El 145.Pp 146See the 147.Sx RECEIVE AND SEND 148section for details on using the chains. 149.Pp 150When bringing an interface down from 151.Xr if_stop 9 , 152which happens under 153.Xr IFNET_LOCK 9 , 154.Nm 155will: 156.Bl -enum 157.It 158abort the USB pipes, 159.It 160call 161.Dq uno_stop 162to stop the hardware from receiving packets (unless the device is 163detaching), 164.It 165free Rx and Tx buffers for transfers, and 166.It 167close the USB pipes. 168.El 169.Pp 170For interface ioctl, most of the handling is in the framework. 171While the interface is running, the optional 172.Dq uno_mcast 173callback is invoked after handling the 174.Dv SIOCADDMULTI 175and 176.Dv SIOCDELMULTI 177ioctl commands to update the hardware's multicast filter from the 178.Xr ethersubr 9 179lists. 180The optional 181.Dq uno_ioctl 182callback, which is invoked under 183.Xr IFNET_LOCK 9 , 184can be used to program special settings like offload handling. 185.Pp 186If ioctl handling requires capturing device-specific ioctls then the 187.Dq uno_override_ioctl 188callback may be used instead to replace the framework's 189ioctl handler completely (i.e., the replacement should call any generic 190ioctl handlers such as 191.Fn ether_ioctl 192as required.) 193For sending packets, the 194.Dq uno_tx_prepare 195callback must be used to convert 196an mbuf into a chain buffer ready for transmission. 197.Pp 198For devices requiring MII handling there are callbacks for reading and 199writing registers, and for status change events. 200Access to all the MII functions is serialized by 201.Nm . 202.Pp 203As receive must handle the case of multiple packets in one buffer, 204the support is split between the driver and the framework. 205A 206.Dq uno_rx_loop 207callback must be provided that loops over the incoming 208packet data found in a chain, performs necessary checking and passes 209the network frame up the stack via either 210.Fn usbnet_enqueue 211or 212.Fn usbnet_input . 213Typically Ethernet devices prefer 214.Fn usbnet_enqueue . 215.Pp 216General accessor functions for 217.Fa struct usbnet : 218.Bl -tag -width 4n 219.It Fn usbnet_set_link un link 220Set the link status for this 221.Fa un 222to 223.Fa link . 224.It Fn usbnet_ifp un 225Returns pointer to this 226.Fa un Ns 's 227.Va struct ifnet . 228.It Fn usbnet_ec un 229Returns pointer to this 230.Fa un Ns 's 231.Va struct ethercom . 232.It Fn usbnet_mii un 233Returns pointer to this 234.Fa un Ns 's 235.Va struct mii_data . 236.It Fn usbnet_rndsrc un 237Returns pointer to this 238.Fa un Ns 's 239.Va krndsource_t . 240.It Fn usbnet_softc un 241Returns pointer to this 242.Fa un Ns 's 243device softc. 244.It Fn usbnet_havelink un 245Returns true if link is active. 246.It Fn usbnet_isdying un 247Returns true if device is dying (has been pulled or deactivated, 248pending detach). 249This should be used only to abort timeout loops early. 250.El 251.Pp 252Buffer enqueue handling for 253.Fa struct usbnet : 254.Bl -tag -width 4n 255.It Fn usbnet_enqueue un buf buflen csum_flags csum_data mbuf_flags 256Enqueue buffer 257.Fa buf 258for length 259.Fa buflen 260with higher layers, using the provided 261.Fa csum_flags , 262and 263.Fa csum_data , 264which are written directly to the mbuf packet header, and 265.Fa mbuf_flags , 266which is or-ed into the mbuf flags for the created mbuf. 267.It Fn usbnet_input un buf buflen 268Enqueue buffer 269.Fa buf 270for length 271.Fa buflen 272with higher layers. 273.El 274.Pp 275Autoconfiguration handling for 276.Fa struct usbnet . 277See the 278.Sx AUTOCONFIGURATION 279section for more details about these functions. 280.Bl -tag -width 4n 281.It Fn usbnet_attach un 282Initial stage attach of a usb network device. 283Performs internal initialization and memory allocation only \(em 284nothing is published yet. 285.It Fn usbnet_attach_ifp un if_flags if_extflags unm 286Final stage attach of usb network device. 287Publishes the network interface to the rest of the system. 288.Pp 289If the passed in 290.Fa unm 291is 292.Pf non- Dv NULL 293then an MII interface will be created using the values 294provided in the 295.Fa struct usbnet_mii 296structure, which has these members passed to 297.Fn mii_attach : 298.Bl -tag -width "un_mii_capmask" 299.It un_mii_flags 300Flags. 301.It un_mii_capmask 302Capability mask. 303.It un_mii_phyloc 304PHY location. 305.It un_mii_offset 306PHY offset. 307.El 308.Pp 309A default 310.Fa unm 311can be set using the 312.Fn USBNET_MII_DECL_DEFAULT 313macro. 314The 315.Fa if_flags 316and 317.Fa if_extflags 318will be or-ed into the interface flags and extflags. 319.It Fn usbnet_detach dev flags 320Device detach. 321Stops all activity and frees memory. 322Usable as 323.Xr driver 9 324detach method. 325.It Fn usbnet_activate dev act 326Device activate (deactivate) method. 327Usable as 328.Xr driver 9 329activate method. 330.El 331.Sh AUTOCONFIGURATION 332The framework expects the usbnet structure to have these members 333filled in with valid values or functions: 334.Bl -tag -width 6n 335.It un_sc 336Real softc allocated by autoconf and provided to attach, should be 337set to the usbnet structure if no device-specific softc is needed. 338.It un_dev 339device_t saved in attach, used for messages mostly. 340.It un_iface 341The USB iface handle for data interactions, see 342.Fn usbd_device2interface_handle 343for more details. 344.It un_udev 345The struct usbd_device for this device, provided as the usb_attach_arg's 346.Va uaa_device 347member. 348.It un_ops 349Points to a 350.Va struct usbnet_ops 351structure which contains these members: 352.Bl -tag -width 4n 353.It Ft void Fn (*uno_stop) "struct ifnet *ifp" "int disable" 354Stop hardware activity 355.Pq optional . 356Called under 357.Xr IFNET_LOCK 9 358when bringing the interface down, but skipped when the device is 359detaching. 360.It Ft int Fn (*uno_ioctl) "struct ifnet *ifp" "u_long cmd" "void *data" 361Handle driver-specific ioctls 362.Pq optional . 363Called under 364.Xr IFNET_LOCK 9 . 365.It Ft void Fn (*uno_mcast) "struct ifnet *" 366Program hardware multicast filters from 367.Xr ethersubr 9 368lists 369.Pq optional . 370Called between, and not during, 371.Dq uno_init 372and 373.Dq uno_stop . 374.It Ft int Fn (*uno_override_ioctl) "struct ifnet *ifp" "u_long cmd" "void *data" 375Handle all ioctls, including standard ethernet ioctls normally handled 376internally by 377.Nm 378.Pq optional . 379May or may not be called under 380.Xr IFNET_LOCK 9 . 381.It Ft int Fn (*uno_init) "struct ifnet *ifp" 382Initialize hardware activity 383.Pq optional . 384Called under 385.Xr IFNET_LOCK 9 386when bringing the interface up. 387.It Ft int Fn (*uno_read_reg) "struct usbnet *un" "int phy" "int reg" "uint16_t *val" 388Read MII register. 389Required with MII. 390Serialized with other MII functions, and with 391.Dq uno_init 392and 393.Dq uno_stop . 394.It Ft int Fn (*uno_write_reg) "struct usbnet *un" "int phy" "int reg" "uint16_t val" 395Write MII register. 396Required with MII. 397Serialized with other MII functions, and with 398.Dq uno_init 399and 400.Dq uno_stop . 401.It Ft usbd_status Fn (*uno_statchg) "struct ifnet *ifp" 402Handle MII status change. 403Required with MII. 404Serialized with other MII functions, and with 405.Dq uno_init 406and 407.Dq uno_stop . 408.It Ft unsigned Fn (*uno_tx_prepare) "struct usbnet *un" "struct mbuf *m" "struct usbnet_chain *c" 409Prepare an mbuf for transmit. 410Required. 411Called sequentially between, and not during, 412.Dq uno_init . 413and 414.Dq uno_stop . 415.It Ft void Fn (*uno_rx_loop) "struct usbnet *un" "struct usbnet_chain *c" "uint32_t total_len" 416Prepare one or more chain for enqueue. 417Required. 418Called sequentially between, and not during, 419.Dq uno_init 420and 421.Dq uno_stop . 422.It Ft void Fn (*uno_intr) "struct usbnet *un" "usbd_status status" 423Process periodic interrupt 424.Pq optional . 425Called sequentially between, and not during, 426.Dq uno_init 427and 428.Dq uno_stop . 429.It Ft void Fn (*uno_tick) "struct usbnet *un" 430Called every second with USB task thread context 431.Pq optional . 432Called sequentially between, and not during, 433.Dq uno_init 434and 435.Dq uno_stop . 436.El 437.It un_intr 438Points to a 439.Va struct usbnet_intr 440structure which should have these members set: 441.Bl -tag -width 4n 442.It uni_buf 443If 444.Pf non- Dv NULL , 445points to a buffer passed to 446.Fn usbd_open_pipe_intr 447in the device init callback, along with the size and interval. 448.It uni_bufsz 449Size of interrupt pipe buffer. 450.It uni_interval 451Frequency of the interrupt in milliseconds. 452.El 453.It un_ed 454Array of endpoint descriptors. 455There indexes are provided: 456.Dv USBNET_ENDPT_RX , 457.Dv USBNET_ENDPT_TX , 458and 459.Dv USBNET_ENDPT_INTR . 460The Rx and Tx endpoints are required. 461.It un_phyno 462MII phy number. 463Not used by 464.Nm . 465.It un_eaddr 4666 bytes of Ethernet address that must be provided before calling 467.Fn usbnet_attach_ifp 468if the device has Ethernet. 469.It un_flags 470Device owned flags word. 471The 472.Nm 473framework will not touch this value. 474.It un_rx_xfer_flags 475Passed to 476.Fn usbd_setup_xfer 477for receiving packets. 478.It un_tx_xfer_flags 479Passed to 480.Fn usbd_setup_xfer 481for sending packets. 482.It un_rx_list_cnt 483Number of chain elements to allocate for Rx. 484.It un_tx_list_cnt 485Number of chain elements to allocate for Tx. 486.It un_rx_bufsz 487Rx buffer size. 488.It un_tx_bufsz 489Tx buffer size. 490.El 491.Pp 492The device detach and activate callbacks can typically be set to 493.Fn usbnet_detach 494and 495.Fn usbnet_activate 496unless device-specific handling is required, in which case, they 497can be called before or after such handling. 498.Pp 499The capabilities described in both 500.Va struct ifp 501and 502.Va struct ethercom 503must be set before calling 504.Fn usbnet_attach_ifp . 505.Sh RECEIVE AND SEND 506Receive and send routines are structured around a the 507.Va usbnet_cdata 508and 509.Va usbnet_chain 510structures, the 511.Dv un_ed , 512.Dv un_rx_xfer_flags , 513and 514.Dv un_tx_xfer_flags 515members, and the 516.Fn uno_stop , 517.Fn uno_init , 518.Fn uno_tx_prepare , 519and 520.Fn uno_rx_loop 521callbacks of 522.Va usbnet_ops . 523.Pp 524Typically, the device attach routine will fill in members of the 525.Va usbnet 526structure, as listed in 527.Sx AUTOCONFIGURATION . 528The 529.Dv un_ed 530array should have the 531.Dv USBNET_ENDPT_RX 532and 533.Dv USBNET_ENDPT_TX 534array entries filled in, and optionally the 535.Dv USBNET_ENDPT_INTR 536entry filled in if applicable. 537.Pp 538The optional 539.Fn uno_stop 540callback performs device-specific operations to shutdown the 541transmit or receive handling. 542.Pp 543The 544.Fn uno_init 545callback both performs device-specific enablement and then calls 546.Fn usbnet_rx_tx_init , 547which sets up the receive, transmit, and, optionally, the interrupt 548pipes, as well as starting the receive pipes. 549All USB transfer setup is handled internally to the framework, and 550the driver callbacks merely copy data in or out of a chain entry using 551what is typically a device-specific method. 552.Pp 553The 554.Fn uno_rx_loop 555callback, called sequentially, converts the provided 556.Va usbnet_chain 557data and length into a series (one or more) of packets that are 558enqueued with the higher layers using either 559.Fn usbnet_enqueue 560(for most devices) or 561.Fn usbnet_input 562for devices that use 563.Fn if_input 564. 565(This currently relies upon the 566.Va struct ifnet 567having the 568.Dq _if_input 569member set as well, which is true for current consumers.) 570.Pp 571The 572.Fn uno_tx_prepare 573callback must convert the provided 574.Va struct mbuf 575into the provided 576.Va struct usbnet_chain 577performing any device-specific padding, checksum, header or other. 578Note that this callback must check that it is not attempting to copy 579more than the chain buffer size, as set in the 580.Va usbnet 581.Dq un_tx_bufsz 582member. 583This callback is only called once per packet, sequentially. 584.Pp 585The 586.Fa struct usbnet_chain 587structure which contains a 588.Dq unc_buf 589member which has the chain buffer allocated where data should be 590copied to or from for receive or transmit operations. 591It also contains pointers back to the owning 592.Fa struct usbnet , 593and the 594.Va struct usbd_xfer 595associated with this transfer. 596.Sh MII 597For devices that have MII support these callbacks in 598.Fa struct usbnet_ops 599must be provided: 600.Bl -tag -width 4n 601.It uno_read_reg 602Read an MII register for a particular PHY. 603Returns standard 604.Xr errno 2 . 605Must initialize the result even on failure. 606.It uno_write_reg 607Write an MII register for a particular PHY. 608Returns standard 609.Xr errno 2 . 610.It uno_statchg 611Handle a status change event for this interface. 612.El 613.Sh INTERRUPT PIPE 614The interrupt specific callback, 615.Dq uno_intr , 616is an optional callback that can be called periodically, registered by 617.Nm 618using the 619.Fn usbd_open_pipe_intr 620function (instead of the 621.Fn usbd_open_pipe 622function.) 623The 624.Nm 625framework provides most of the interrupt handling and the callback 626simply inspects the returned buffer as necessary. 627To enable the this callback point the 628.Va struct usbnet 629member 630.Dq un_intr 631to a 632.Va struct usbnet_intr 633structure with these members set: 634.Bl -tag -width 4n 635.It uni_buf 636Data buffer for interrupt status relies. 637.It uni_bufsz 638Size of the above buffer. 639.It uni_interval 640Interval in millieconds. 641.El 642.Pp 643These values will be passed to 644.Fn usbd_open_pipe_intr . 645.Sh CONVERTING OLD-STYLE DRIVERS 646The porting of an older driver to the 647.Nm 648framework is largely an effort in deleting code. 649The process involves making these changes: 650.Bl -tag -width 4n 651.It Headers 652Many headers are included in 653.Pa usbnet.h 654and can be removed from the driver, as well as headers no longer used, 655such as 656.Pa callout.h 657and 658.Pa rndsource.h , 659etc. 660.It Device softc 661The majority of the driver's existing 662.Dq softc 663structure can likely be replaced with usage of 664.Va struct usbnet 665and its related functionality. 666This includes at least the device_t pointer, Ethernet address, the 667ethercom and mii_data structures, end point descriptors, usbd device, 668interface, and task and callout structures (both these probably go 669away entirely) and all the associated watchdog handling, 670timevals, list size, buffer size and xfer flags for 671both Rx, and Tx, and interrupt notices, interface flags, device link, 672PHY number, chain data, locks including Rx, Tx, and MII. 673There is a driver-only 674.Dq un_flags 675in the 676.Va usbnet 677structure available for drivers to use. 678.Pp 679Many drivers can use the 680.Va usbnet 681structure as the device private storage passed to 682.Dv CFATTACH_DECL_NEW . 683Many internal functions to the driver may look better if switched to 684operate on the device's 685.Va usbnet 686as, for example, the 687.Va usbd_device 688value is now available (and must be set by the driver) in the 689.Va usbnet , 690which may be needed for any call to 691.Fn usbd_do_request . 692The standard endpoint values must be stored in the 693.Nm 694.Dq un_ed[] 695array. 696.Pp 697As 698.Nm 699manages xfer chains all code related to the opening, closing, aborting 700and transferring of data on pipes is performed by the framework based 701upon the buffer size and more provided in 702.Va subnet , 703so all code related to them should be deleted. 704.It Interface setup 705The vast majority of interface specific code should be deleted. 706For device-specific interface values, the 707.Va ifnet 708flags and exflags can be set, as well as the 709.Va ethercom 710.Dq ec_capabilities 711member, before calling 712.Fn usbnet_attach_ifp . 713All calls to 714.Fn ifmedia_init , 715.Fn mii_attach , 716.Fn ifmedia_add , 717.Fn ifmedia_set , 718.Fn if_attach , 719.Fn ether_ifattach , 720.Fn rnd_attach_source , 721and 722.Fn usbd_add_drv_event 723should be eliminated. 724The device 725.Dq ioctl 726routine can use the default handling with a callback for additional 727device specific programming (multicast filters, etc.), which can be 728empty, or, the override ioctl can be used for heavier requirements. 729The device 730.Dq stop 731routine is replaced with a simple call that turns off the 732device-specific transmitter and receiver if necessary, as the 733framework handles pipes and transfers and buffers. 734.It MII handling 735For devices with MII support the three normal callbacks 736.Pq read, write, and status change 737must be converted to 738.Va usbnet . 739Local 740.Dq link 741variables need to be replaced with accesses to 742.Fn usbnet_set_link 743and 744.Fn usbnet_havelink . 745Other ifmedia callbacks that were passed to 746.Fn ifmedia_init 747should be deleted and any work moved into 748.Dq uno_statchg . 749.It Receive and Transmit 750The 751.Nm 752framework handles the majority of handling of both network directions. 753The interface init routine should keep all of the device specific setup 754but replace all pipe management with a call to 755.Fn usbnet_init_rx_tx . 756The typical receive handling will normally be replaced with a receive 757loop functions that can accept one or more packets, 758.Dq uno_rx_loop , 759which can use either 760.Fn usbnet_enqueue 761or 762.Fn usbnet_input 763to pass the packets up to higher layers. 764The typical interface 765.Dq if_start 766function and any additional functions used will normal be replaced 767with a relatively simple 768.Dq uno_tx_prepare 769function that simply converts an 770.Va mbuf 771into a 772.Va usbnet_chain 773useful for this device that will be passed onto 774.Fn usbd_transfer . 775The framework's handling of the Tx interrupt is all internal. 776.It Interrupt pipe handling 777For devices requiring special handling of the interrupt pipe (i.e., 778they use the 779.Fn usbd_open_pipe_intr 780method), most of the interrupt handler should be deleted, leaving 781only code that inspects the result of the interrupt transfer. 782.It Common errors 783It's common to forget to set link active on devices with MII. 784Be sure to call 785.Fn usbent_set_link 786during any status change event. 787.Pp 788Many locking issues are hidden without 789.Dv LOCKDEBUG , 790including hard-hangs. 791It's highly recommended to develop with 792.Dv LOCKDEBUG . 793.Pp 794The 795.Va usbnet 796.Dq un_ed 797array is unsigned and should use 798.Dq 0 799as the no-endpoint value. 800.El 801.Sh SEE ALSO 802.Xr usb 4 , 803.Xr driver 9 , 804.Xr usbd_status 9 , 805.Xr usbdi 9 806.Sh HISTORY 807This 808.Nm 809interface first appeared in 810.Nx 9.0 . 811Portions of the original design are based upon ideas from 812.An Nick Hudson Aq Mt skrll@NetBSD.org . 813.Sh AUTHORS 814.An Matthew R. Green Aq Mt mrg@eterna.com.au 815