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