1 /* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-4-Clause 5 * 6 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> 7 * Copyright (c) 2003-2005 Craig Boston 8 * Copyright (c) 2004 Daniel Hartmeier 9 * Copyright (c) 2009 Hans Petter Selasky 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by Bill Paul. 23 * 4. Neither the name of the author nor the names of any co-contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR 31 * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 33 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 34 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 35 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 36 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 37 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * USB Communication Device Class (Ethernet Networking Control Model) 42 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf 43 */ 44 45 /* 46 * USB Network Control Model (NCM) 47 * http://www.usb.org/developers/devclass_docs/NCM10.zip 48 */ 49 50 #include <sys/cdefs.h> 51 #include <sys/gsb_crc32.h> 52 #include <sys/eventhandler.h> 53 #include <sys/stdint.h> 54 #include <sys/stddef.h> 55 #include <sys/queue.h> 56 #include <sys/systm.h> 57 #include <sys/socket.h> 58 #include <sys/kernel.h> 59 #include <sys/bus.h> 60 #include <sys/module.h> 61 #include <sys/lock.h> 62 #include <sys/mutex.h> 63 #include <sys/condvar.h> 64 #include <sys/sysctl.h> 65 #include <sys/sx.h> 66 #include <sys/unistd.h> 67 #include <sys/callout.h> 68 #include <sys/malloc.h> 69 #include <sys/priv.h> 70 71 #include <net/if.h> 72 #include <net/if_var.h> 73 74 #include <dev/usb/usb.h> 75 #include <dev/usb/usbdi.h> 76 #include <dev/usb/usbdi_util.h> 77 #include <dev/usb/usb_cdc.h> 78 #include "usbdevs.h" 79 80 #define USB_DEBUG_VAR cdce_debug 81 #include <dev/usb/usb_debug.h> 82 #include <dev/usb/usb_process.h> 83 #include <dev/usb/usb_msctest.h> 84 #include "usb_if.h" 85 86 #include <dev/usb/net/usb_ethernet.h> 87 #include <dev/usb/net/if_cdcereg.h> 88 89 static device_probe_t cdce_probe; 90 static device_attach_t cdce_attach; 91 static device_detach_t cdce_detach; 92 static device_suspend_t cdce_suspend; 93 static device_resume_t cdce_resume; 94 static usb_handle_request_t cdce_handle_request; 95 96 static usb_callback_t cdce_bulk_write_callback; 97 static usb_callback_t cdce_bulk_read_callback; 98 static usb_callback_t cdce_intr_read_callback; 99 static usb_callback_t cdce_intr_write_callback; 100 101 #if CDCE_HAVE_NCM 102 static usb_callback_t cdce_ncm_bulk_write_callback; 103 static usb_callback_t cdce_ncm_bulk_read_callback; 104 #endif 105 106 static uether_fn_t cdce_attach_post; 107 static uether_fn_t cdce_init; 108 static uether_fn_t cdce_stop; 109 static uether_fn_t cdce_start; 110 static uether_fn_t cdce_setmulti; 111 static uether_fn_t cdce_setpromisc; 112 static int cdce_attach_post_sub(struct usb_ether *); 113 static int cdce_ioctl(if_t, u_long, caddr_t); 114 static int cdce_media_change_cb(if_t); 115 static void cdce_media_status_cb(if_t, struct ifmediareq *); 116 117 static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t); 118 static void cdce_set_filter(struct usb_ether *); 119 120 #ifdef USB_DEBUG 121 static int cdce_debug = 0; 122 static int cdce_tx_interval = 0; 123 124 static SYSCTL_NODE(_hw_usb, OID_AUTO, cdce, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 125 "USB CDC-Ethernet"); 126 SYSCTL_INT(_hw_usb_cdce, OID_AUTO, debug, CTLFLAG_RWTUN, &cdce_debug, 0, 127 "Debug level"); 128 SYSCTL_INT(_hw_usb_cdce, OID_AUTO, interval, CTLFLAG_RWTUN, &cdce_tx_interval, 0, 129 "NCM transmit interval in ms"); 130 #else 131 #define cdce_debug 0 132 #endif 133 134 static const struct usb_config cdce_config[CDCE_N_TRANSFER] = { 135 [CDCE_BULK_RX] = { 136 .type = UE_BULK, 137 .endpoint = UE_ADDR_ANY, 138 .direction = UE_DIR_RX, 139 .if_index = 0, 140 .frames = CDCE_FRAMES_MAX, 141 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 142 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,}, 143 .callback = cdce_bulk_read_callback, 144 .timeout = 0, /* no timeout */ 145 .usb_mode = USB_MODE_DUAL, /* both modes */ 146 }, 147 148 [CDCE_BULK_TX] = { 149 .type = UE_BULK, 150 .endpoint = UE_ADDR_ANY, 151 .direction = UE_DIR_TX, 152 .if_index = 0, 153 .frames = CDCE_FRAMES_MAX, 154 .bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 155 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,}, 156 .callback = cdce_bulk_write_callback, 157 .timeout = 10000, /* 10 seconds */ 158 .usb_mode = USB_MODE_DUAL, /* both modes */ 159 }, 160 161 [CDCE_INTR_RX] = { 162 .type = UE_INTERRUPT, 163 .endpoint = UE_ADDR_ANY, 164 .direction = UE_DIR_RX, 165 .if_index = 1, 166 .bufsize = CDCE_IND_SIZE_MAX, 167 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, 168 .callback = cdce_intr_read_callback, 169 .timeout = 0, 170 .usb_mode = USB_MODE_HOST, 171 }, 172 173 [CDCE_INTR_TX] = { 174 .type = UE_INTERRUPT, 175 .endpoint = UE_ADDR_ANY, 176 .direction = UE_DIR_TX, 177 .if_index = 1, 178 .bufsize = CDCE_IND_SIZE_MAX, 179 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 180 .callback = cdce_intr_write_callback, 181 .timeout = 10000, /* 10 seconds */ 182 .usb_mode = USB_MODE_DEVICE, 183 }, 184 }; 185 186 #if CDCE_HAVE_NCM 187 static const struct usb_config cdce_ncm_config[CDCE_N_TRANSFER] = { 188 [CDCE_BULK_RX] = { 189 .type = UE_BULK, 190 .endpoint = UE_ADDR_ANY, 191 .direction = UE_DIR_RX, 192 .if_index = 0, 193 .frames = CDCE_NCM_RX_FRAMES_MAX, 194 .bufsize = (CDCE_NCM_RX_FRAMES_MAX * CDCE_NCM_RX_MAXLEN), 195 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,}, 196 .callback = cdce_ncm_bulk_read_callback, 197 .timeout = 0, /* no timeout */ 198 .usb_mode = USB_MODE_DUAL, /* both modes */ 199 }, 200 201 [CDCE_BULK_TX] = { 202 .type = UE_BULK, 203 .endpoint = UE_ADDR_ANY, 204 .direction = UE_DIR_TX, 205 .if_index = 0, 206 .frames = CDCE_NCM_TX_FRAMES_MAX, 207 .bufsize = (CDCE_NCM_TX_FRAMES_MAX * CDCE_NCM_TX_MAXLEN), 208 .flags = {.pipe_bof = 1,}, 209 .callback = cdce_ncm_bulk_write_callback, 210 .timeout = 10000, /* 10 seconds */ 211 .usb_mode = USB_MODE_DUAL, /* both modes */ 212 }, 213 214 [CDCE_INTR_RX] = { 215 .type = UE_INTERRUPT, 216 .endpoint = UE_ADDR_ANY, 217 .direction = UE_DIR_RX, 218 .if_index = 1, 219 .bufsize = CDCE_IND_SIZE_MAX, 220 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, 221 .callback = cdce_intr_read_callback, 222 .timeout = 0, 223 .usb_mode = USB_MODE_HOST, 224 }, 225 226 [CDCE_INTR_TX] = { 227 .type = UE_INTERRUPT, 228 .endpoint = UE_ADDR_ANY, 229 .direction = UE_DIR_TX, 230 .if_index = 1, 231 .bufsize = CDCE_IND_SIZE_MAX, 232 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 233 .callback = cdce_intr_write_callback, 234 .timeout = 10000, /* 10 seconds */ 235 .usb_mode = USB_MODE_DEVICE, 236 }, 237 }; 238 #endif 239 240 static device_method_t cdce_methods[] = { 241 /* USB interface */ 242 DEVMETHOD(usb_handle_request, cdce_handle_request), 243 244 /* Device interface */ 245 DEVMETHOD(device_probe, cdce_probe), 246 DEVMETHOD(device_attach, cdce_attach), 247 DEVMETHOD(device_detach, cdce_detach), 248 DEVMETHOD(device_suspend, cdce_suspend), 249 DEVMETHOD(device_resume, cdce_resume), 250 251 DEVMETHOD_END 252 }; 253 254 static driver_t cdce_driver = { 255 .name = "cdce", 256 .methods = cdce_methods, 257 .size = sizeof(struct cdce_softc), 258 }; 259 260 static eventhandler_tag cdce_etag; 261 262 static int cdce_driver_loaded(struct module *, int, void *); 263 264 static const STRUCT_USB_HOST_ID cdce_switch_devs[] = { 265 {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E3272_INIT, MSC_EJECT_HUAWEI2)}, 266 {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E3372v153_INIT, MSC_EJECT_HUAWEI2)}, 267 {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E3372_INIT, MSC_EJECT_HUAWEI4)}, 268 {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E5573Cs322_ECM, MSC_EJECT_HUAWEI3)}, 269 }; 270 271 static const STRUCT_USB_HOST_ID cdce_host_devs[] = { 272 {USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)}, 273 {USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)}, 274 {USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)}, 275 {USB_VPI(USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00, CDCE_FLAG_NO_UNION)}, 276 {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 277 {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 278 {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501, CDCE_FLAG_NO_UNION)}, 279 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)}, 280 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 281 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 282 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 283 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 284 285 {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), 286 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x16), 287 USB_DRIVER_INFO(0)}, 288 {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), 289 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x46), 290 USB_DRIVER_INFO(0)}, 291 {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), 292 USB_IFACE_SUBCLASS(0x02), USB_IFACE_PROTOCOL(0x76), 293 USB_DRIVER_INFO(0)}, 294 {USB_VENDOR(USB_VENDOR_HUAWEI), USB_IFACE_CLASS(UICLASS_VENDOR), 295 USB_IFACE_SUBCLASS(0x03), USB_IFACE_PROTOCOL(0x16), 296 USB_DRIVER_INFO(0)}, 297 }; 298 299 static const STRUCT_USB_DUAL_ID cdce_dual_devs[] = { 300 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)}, 301 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)}, 302 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_NETWORK_CONTROL_MODEL, 0)}, 303 }; 304 305 DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_driver_loaded, NULL); 306 MODULE_VERSION(cdce, 1); 307 MODULE_DEPEND(cdce, uether, 1, 1, 1); 308 MODULE_DEPEND(cdce, usb, 1, 1, 1); 309 MODULE_DEPEND(cdce, ether, 1, 1, 1); 310 USB_PNP_DEVICE_INFO(cdce_switch_devs); 311 USB_PNP_HOST_INFO(cdce_host_devs); 312 USB_PNP_DUAL_INFO(cdce_dual_devs); 313 314 static const struct usb_ether_methods cdce_ue_methods = { 315 .ue_attach_post = cdce_attach_post, 316 .ue_attach_post_sub = cdce_attach_post_sub, 317 .ue_start = cdce_start, 318 .ue_init = cdce_init, 319 .ue_stop = cdce_stop, 320 .ue_setmulti = cdce_setmulti, 321 .ue_setpromisc = cdce_setpromisc, 322 }; 323 324 #if CDCE_HAVE_NCM 325 /*------------------------------------------------------------------------* 326 * cdce_ncm_init 327 * 328 * Return values: 329 * 0: Success 330 * Else: Failure 331 *------------------------------------------------------------------------*/ 332 static uint8_t 333 cdce_ncm_init(struct cdce_softc *sc) 334 { 335 struct usb_ncm_parameters temp; 336 struct usb_device_request req; 337 struct usb_ncm_func_descriptor *ufd; 338 uint8_t value[8]; 339 int err; 340 341 ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL, 342 sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0xFF, 343 UCDC_NCM_FUNC_DESC_SUBTYPE, 0xFF); 344 345 /* verify length of NCM functional descriptor */ 346 if (ufd != NULL) { 347 if (ufd->bLength < sizeof(*ufd)) 348 ufd = NULL; 349 else 350 DPRINTFN(1, "Found NCM functional descriptor.\n"); 351 } 352 353 req.bmRequestType = UT_READ_CLASS_INTERFACE; 354 req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS; 355 USETW(req.wValue, 0); 356 req.wIndex[0] = sc->sc_ifaces_index[1]; 357 req.wIndex[1] = 0; 358 USETW(req.wLength, sizeof(temp)); 359 360 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 361 &temp, 0, NULL, 1000 /* ms */); 362 if (err) 363 return (1); 364 365 /* Read correct set of parameters according to device mode */ 366 367 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 368 sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize); 369 sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize); 370 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder); 371 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor); 372 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment); 373 sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); 374 } else { 375 sc->sc_ncm.rx_max = UGETDW(temp.dwNtbOutMaxSize); 376 sc->sc_ncm.tx_max = UGETDW(temp.dwNtbInMaxSize); 377 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder); 378 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor); 379 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment); 380 sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams); 381 } 382 383 /* Verify maximum receive length */ 384 385 if ((sc->sc_ncm.rx_max < 32) || 386 (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) { 387 DPRINTFN(1, "Using default maximum receive length\n"); 388 sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN; 389 } 390 391 /* Verify maximum transmit length */ 392 393 if ((sc->sc_ncm.tx_max < 32) || 394 (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) { 395 DPRINTFN(1, "Using default maximum transmit length\n"); 396 sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN; 397 } 398 399 /* 400 * Verify that the structure alignment is: 401 * - power of two 402 * - not greater than the maximum transmit length 403 * - not less than four bytes 404 */ 405 if ((sc->sc_ncm.tx_struct_align < 4) || 406 (sc->sc_ncm.tx_struct_align != 407 ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) || 408 (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) { 409 DPRINTFN(1, "Using default other alignment: 4 bytes\n"); 410 sc->sc_ncm.tx_struct_align = 4; 411 } 412 413 /* 414 * Verify that the payload alignment is: 415 * - power of two 416 * - not greater than the maximum transmit length 417 * - not less than four bytes 418 */ 419 if ((sc->sc_ncm.tx_modulus < 4) || 420 (sc->sc_ncm.tx_modulus != 421 ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) || 422 (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) { 423 DPRINTFN(1, "Using default transmit modulus: 4 bytes\n"); 424 sc->sc_ncm.tx_modulus = 4; 425 } 426 427 /* Verify that the payload remainder */ 428 429 if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) { 430 DPRINTFN(1, "Using default transmit remainder: 0 bytes\n"); 431 sc->sc_ncm.tx_remainder = 0; 432 } 433 434 /* 435 * Offset the TX remainder so that IP packet payload starts at 436 * the tx_modulus. This is not too clear in the specification. 437 */ 438 439 sc->sc_ncm.tx_remainder = 440 (sc->sc_ncm.tx_remainder - ETHER_HDR_LEN) & 441 (sc->sc_ncm.tx_modulus - 1); 442 443 /* Verify max datagrams */ 444 445 if (sc->sc_ncm.tx_nframe == 0 || 446 sc->sc_ncm.tx_nframe > (CDCE_NCM_SUBFRAMES_MAX - 1)) { 447 DPRINTFN(1, "Using default max " 448 "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX - 1); 449 /* need to reserve one entry for zero padding */ 450 sc->sc_ncm.tx_nframe = (CDCE_NCM_SUBFRAMES_MAX - 1); 451 } 452 453 /* Additional configuration, will fail in device side mode, which is OK. */ 454 455 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 456 req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE; 457 USETW(req.wValue, 0); 458 req.wIndex[0] = sc->sc_ifaces_index[1]; 459 req.wIndex[1] = 0; 460 461 if (ufd != NULL && 462 (ufd->bmNetworkCapabilities & UCDC_NCM_CAP_MAX_DGRAM)) { 463 USETW(req.wLength, 8); 464 USETDW(value, sc->sc_ncm.rx_max); 465 USETW(value + 4, (CDCE_NCM_SUBFRAMES_MAX - 1)); 466 USETW(value + 6, 0); 467 } else { 468 USETW(req.wLength, 4); 469 USETDW(value, sc->sc_ncm.rx_max); 470 } 471 472 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 473 &value, 0, NULL, 1000 /* ms */); 474 if (err) { 475 DPRINTFN(1, "Setting input size " 476 "to %u failed.\n", sc->sc_ncm.rx_max); 477 } 478 479 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 480 req.bRequest = UCDC_NCM_SET_CRC_MODE; 481 USETW(req.wValue, 0); /* no CRC */ 482 req.wIndex[0] = sc->sc_ifaces_index[1]; 483 req.wIndex[1] = 0; 484 USETW(req.wLength, 0); 485 486 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 487 NULL, 0, NULL, 1000 /* ms */); 488 if (err) { 489 DPRINTFN(1, "Setting CRC mode to off failed.\n"); 490 } 491 492 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 493 req.bRequest = UCDC_NCM_SET_NTB_FORMAT; 494 USETW(req.wValue, 0); /* NTB-16 */ 495 req.wIndex[0] = sc->sc_ifaces_index[1]; 496 req.wIndex[1] = 0; 497 USETW(req.wLength, 0); 498 499 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 500 NULL, 0, NULL, 1000 /* ms */); 501 if (err) { 502 DPRINTFN(1, "Setting NTB format to 16-bit failed.\n"); 503 } 504 505 return (0); /* success */ 506 } 507 #endif 508 509 static void 510 cdce_test_autoinst(void *arg, struct usb_device *udev, 511 struct usb_attach_arg *uaa) 512 { 513 struct usb_interface *iface; 514 struct usb_interface_descriptor *id; 515 516 if (uaa->dev_state != UAA_DEV_READY) 517 return; 518 519 iface = usbd_get_iface(udev, 0); 520 if (iface == NULL) 521 return; 522 id = iface->idesc; 523 if (id == NULL || id->bInterfaceClass != UICLASS_MASS) 524 return; 525 if (usbd_lookup_id_by_uaa(cdce_switch_devs, sizeof(cdce_switch_devs), uaa)) 526 return; /* no device match */ 527 528 if (usb_msc_eject(udev, 0, USB_GET_DRIVER_INFO(uaa)) == 0) { 529 /* success, mark the udev as disappearing */ 530 uaa->dev_state = UAA_DEV_EJECTING; 531 } 532 } 533 534 static int 535 cdce_driver_loaded(struct module *mod, int what, void *arg) 536 { 537 switch (what) { 538 case MOD_LOAD: 539 /* register our autoinstall handler */ 540 cdce_etag = EVENTHANDLER_REGISTER(usb_dev_configured, 541 cdce_test_autoinst, NULL, EVENTHANDLER_PRI_ANY); 542 return (0); 543 case MOD_UNLOAD: 544 EVENTHANDLER_DEREGISTER(usb_dev_configured, cdce_etag); 545 return (0); 546 default: 547 return (EOPNOTSUPP); 548 } 549 } 550 551 static int 552 cdce_probe(device_t dev) 553 { 554 struct usb_attach_arg *uaa = device_get_ivars(dev); 555 int error; 556 557 error = usbd_lookup_id_by_uaa(cdce_host_devs, sizeof(cdce_host_devs), uaa); 558 if (error) 559 error = usbd_lookup_id_by_uaa(cdce_dual_devs, sizeof(cdce_dual_devs), uaa); 560 return (error); 561 } 562 563 static void 564 cdce_attach_post(struct usb_ether *ue) 565 { 566 /* no-op */ 567 return; 568 } 569 570 static int 571 cdce_attach_post_sub(struct usb_ether *ue) 572 { 573 struct cdce_softc *sc = uether_getsc(ue); 574 if_t ifp = uether_getifp(ue); 575 576 /* mostly copied from usb_ethernet.c */ 577 if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 578 if_setstartfn(ifp, uether_start); 579 if_setioctlfn(ifp, cdce_ioctl); 580 if_setinitfn(ifp, uether_init); 581 if_setsendqlen(ifp, ifqmaxlen); 582 if_setsendqready(ifp); 583 584 if ((sc->sc_flags & CDCE_FLAG_VLAN) == CDCE_FLAG_VLAN) 585 if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0); 586 587 if_setcapabilitiesbit(ifp, IFCAP_LINKSTATE, 0); 588 if_setcapenable(ifp, if_getcapabilities(ifp)); 589 590 ifmedia_init(&sc->sc_media, IFM_IMASK, cdce_media_change_cb, 591 cdce_media_status_cb); 592 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); 593 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); 594 sc->sc_media.ifm_media = sc->sc_media.ifm_cur->ifm_media; 595 CDCE_LOCK(sc); 596 cdce_set_filter(ue); 597 CDCE_UNLOCK(sc); 598 599 return 0; 600 } 601 602 static int 603 cdce_attach(device_t dev) 604 { 605 struct cdce_softc *sc = device_get_softc(dev); 606 struct usb_ether *ue = &sc->sc_ue; 607 struct usb_attach_arg *uaa = device_get_ivars(dev); 608 struct usb_interface *iface; 609 const struct usb_cdc_union_descriptor *ud; 610 const struct usb_interface_descriptor *id; 611 const struct usb_cdc_ethernet_descriptor *ued; 612 const struct usb_config *pcfg; 613 uint32_t seed; 614 int error; 615 uint8_t i; 616 uint8_t data_iface_no; 617 char eaddr_str[5 * ETHER_ADDR_LEN]; /* approx */ 618 619 sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 620 sc->sc_ue.ue_udev = uaa->device; 621 622 device_set_usb_desc(dev); 623 624 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 625 626 ud = usbd_find_descriptor 627 (uaa->device, NULL, uaa->info.bIfaceIndex, 628 UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_UNION, 0xFF); 629 630 if ((ud == NULL) || (ud->bLength < sizeof(*ud)) || 631 (sc->sc_flags & CDCE_FLAG_NO_UNION)) { 632 DPRINTFN(1, "No union descriptor!\n"); 633 sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex; 634 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 635 goto alloc_transfers; 636 } 637 data_iface_no = ud->bSlaveInterface[0]; 638 639 for (i = 0;; i++) { 640 iface = usbd_get_iface(uaa->device, i); 641 642 if (iface) { 643 id = usbd_get_interface_descriptor(iface); 644 645 if (id && (id->bInterfaceNumber == data_iface_no)) { 646 sc->sc_ifaces_index[0] = i; 647 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 648 usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); 649 break; 650 } 651 } else { 652 device_printf(dev, "no data interface found\n"); 653 goto detach; 654 } 655 } 656 657 /* 658 * <quote> 659 * 660 * The Data Class interface of a networking device shall have 661 * a minimum of two interface settings. The first setting 662 * (the default interface setting) includes no endpoints and 663 * therefore no networking traffic is exchanged whenever the 664 * default interface setting is selected. One or more 665 * additional interface settings are used for normal 666 * operation, and therefore each includes a pair of endpoints 667 * (one IN, and one OUT) to exchange network traffic. Select 668 * an alternate interface setting to initialize the network 669 * aspects of the device and to enable the exchange of 670 * network traffic. 671 * 672 * </quote> 673 * 674 * Some devices, most notably cable modems, include interface 675 * settings that have no IN or OUT endpoint, therefore loop 676 * through the list of all available interface settings 677 * looking for one with both IN and OUT endpoints. 678 */ 679 680 alloc_transfers: 681 682 pcfg = cdce_config; /* Default Configuration */ 683 684 for (i = 0; i != 32; i++) { 685 error = usbd_set_alt_interface_index(uaa->device, 686 sc->sc_ifaces_index[0], i); 687 if (error) 688 break; 689 #if CDCE_HAVE_NCM 690 if ((i == 0) && (cdce_ncm_init(sc) == 0)) 691 pcfg = cdce_ncm_config; 692 #endif 693 error = usbd_transfer_setup(uaa->device, 694 sc->sc_ifaces_index, sc->sc_xfer, 695 pcfg, CDCE_N_TRANSFER, sc, &sc->sc_mtx); 696 697 if (error == 0) 698 break; 699 } 700 701 if (error || (i == 32)) { 702 device_printf(dev, "No valid alternate " 703 "setting found\n"); 704 goto detach; 705 } 706 707 ued = usbd_find_descriptor 708 (uaa->device, NULL, uaa->info.bIfaceIndex, 709 UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_ENF, 0xFF); 710 711 if ((ued == NULL) || (ued->bLength < sizeof(*ued))) { 712 error = USB_ERR_INVAL; 713 } else { 714 /* 715 * ECM 1.2 doesn't say it excludes the CRC, but states that it's 716 * normally 1514, which excludes the CRC. 717 */ 718 DPRINTF("max segsize: %d\n", UGETW(ued->wMaxSegmentSize)); 719 if (UGETW(ued->wMaxSegmentSize) >= (ETHER_MAX_LEN - ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN)) 720 sc->sc_flags |= CDCE_FLAG_VLAN; 721 722 error = usbd_req_get_string_any(uaa->device, NULL, 723 eaddr_str, sizeof(eaddr_str), ued->iMacAddress); 724 } 725 726 if (error) { 727 /* fake MAC address */ 728 729 device_printf(dev, "faking MAC address\n"); 730 seed = ticks; 731 sc->sc_ue.ue_eaddr[0] = 0x2a; 732 memcpy(&sc->sc_ue.ue_eaddr[1], &seed, sizeof(uint32_t)); 733 sc->sc_ue.ue_eaddr[5] = device_get_unit(dev); 734 735 } else { 736 memset(sc->sc_ue.ue_eaddr, 0, sizeof(sc->sc_ue.ue_eaddr)); 737 738 for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) { 739 char c = eaddr_str[i]; 740 741 if ('0' <= c && c <= '9') 742 c -= '0'; 743 else if (c != 0) 744 c -= 'A' - 10; 745 else 746 break; 747 748 c &= 0xf; 749 750 if ((i & 1) == 0) 751 c <<= 4; 752 sc->sc_ue.ue_eaddr[i / 2] |= c; 753 } 754 755 if (uaa->usb_mode == USB_MODE_DEVICE) { 756 /* 757 * Do not use the same MAC address like the peer ! 758 */ 759 sc->sc_ue.ue_eaddr[5] ^= 0xFF; 760 } 761 } 762 763 ue->ue_sc = sc; 764 ue->ue_dev = dev; 765 ue->ue_udev = uaa->device; 766 ue->ue_mtx = &sc->sc_mtx; 767 ue->ue_methods = &cdce_ue_methods; 768 769 error = uether_ifattach(ue); 770 if (error) { 771 device_printf(dev, "could not attach interface\n"); 772 goto detach; 773 } 774 return (0); /* success */ 775 776 detach: 777 cdce_detach(dev); 778 return (ENXIO); /* failure */ 779 } 780 781 static int 782 cdce_detach(device_t dev) 783 { 784 struct cdce_softc *sc = device_get_softc(dev); 785 struct usb_ether *ue = &sc->sc_ue; 786 787 /* stop all USB transfers first */ 788 usbd_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER); 789 uether_ifdetach(ue); 790 mtx_destroy(&sc->sc_mtx); 791 792 ifmedia_removeall(&sc->sc_media); 793 794 return (0); 795 } 796 797 static void 798 cdce_start(struct usb_ether *ue) 799 { 800 struct cdce_softc *sc = uether_getsc(ue); 801 802 /* 803 * Start the USB transfers, if not already started: 804 */ 805 usbd_transfer_start(sc->sc_xfer[CDCE_BULK_TX]); 806 usbd_transfer_start(sc->sc_xfer[CDCE_BULK_RX]); 807 } 808 809 static int 810 cdce_ioctl(if_t ifp, u_long command, caddr_t data) 811 { 812 struct usb_ether *ue = if_getsoftc(ifp); 813 struct cdce_softc *sc = uether_getsc(ue); 814 struct ifreq *ifr = (struct ifreq *)data; 815 int error; 816 817 error = 0; 818 819 switch(command) { 820 case SIOCGIFMEDIA: 821 case SIOCSIFMEDIA: 822 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command); 823 break; 824 default: 825 error = uether_ioctl(ifp, command, data); 826 break; 827 } 828 829 return (error); 830 } 831 832 static void 833 cdce_free_queue(struct mbuf **ppm, uint8_t n) 834 { 835 uint8_t x; 836 for (x = 0; x != n; x++) { 837 if (ppm[x] != NULL) { 838 m_freem(ppm[x]); 839 ppm[x] = NULL; 840 } 841 } 842 } 843 844 static int 845 cdce_media_change_cb(if_t ifp) 846 { 847 848 return (EOPNOTSUPP); 849 } 850 851 static void 852 cdce_media_status_cb(if_t ifp, struct ifmediareq *ifmr) 853 { 854 855 if ((if_getflags(ifp) & IFF_UP) == 0) 856 return; 857 858 ifmr->ifm_active = IFM_ETHER; 859 ifmr->ifm_status = IFM_AVALID; 860 ifmr->ifm_status |= 861 if_getlinkstate(ifp) == LINK_STATE_UP ? IFM_ACTIVE : 0; 862 } 863 864 static void 865 cdce_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 866 { 867 struct cdce_softc *sc = usbd_xfer_softc(xfer); 868 if_t ifp = uether_getifp(&sc->sc_ue); 869 struct mbuf *m; 870 struct mbuf *mt; 871 uint32_t crc; 872 uint8_t x; 873 int actlen, aframes; 874 875 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 876 877 DPRINTFN(1, "\n"); 878 879 switch (USB_GET_STATE(xfer)) { 880 case USB_ST_TRANSFERRED: 881 DPRINTFN(11, "transfer complete: %u bytes in %u frames\n", 882 actlen, aframes); 883 884 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 885 886 /* free all previous TX buffers */ 887 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 888 889 /* FALLTHROUGH */ 890 case USB_ST_SETUP: 891 tr_setup: 892 for (x = 0; x != CDCE_FRAMES_MAX; x++) { 893 m = if_dequeue(ifp); 894 895 if (m == NULL) 896 break; 897 898 if (sc->sc_flags & CDCE_FLAG_ZAURUS) { 899 /* 900 * Zaurus wants a 32-bit CRC appended 901 * to every frame 902 */ 903 904 crc = cdce_m_crc32(m, 0, m->m_pkthdr.len); 905 crc = htole32(crc); 906 907 if (!m_append(m, 4, (void *)&crc)) { 908 m_freem(m); 909 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 910 continue; 911 } 912 } 913 if (m->m_len != m->m_pkthdr.len) { 914 mt = m_defrag(m, M_NOWAIT); 915 if (mt == NULL) { 916 m_freem(m); 917 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 918 continue; 919 } 920 m = mt; 921 } 922 if (m->m_pkthdr.len > MCLBYTES) { 923 m->m_pkthdr.len = MCLBYTES; 924 } 925 sc->sc_tx_buf[x] = m; 926 usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len); 927 928 /* 929 * If there's a BPF listener, bounce a copy of 930 * this frame to him: 931 */ 932 BPF_MTAP(ifp, m); 933 } 934 if (x != 0) { 935 usbd_xfer_set_frames(xfer, x); 936 937 usbd_transfer_submit(xfer); 938 } 939 break; 940 941 default: /* Error */ 942 DPRINTFN(11, "transfer error, %s\n", 943 usbd_errstr(error)); 944 945 /* free all previous TX buffers */ 946 cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 947 948 /* count output errors */ 949 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 950 951 if (error != USB_ERR_CANCELLED) { 952 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 953 /* try to clear stall first */ 954 usbd_xfer_set_stall(xfer); 955 } 956 goto tr_setup; 957 } 958 break; 959 } 960 } 961 962 static int32_t 963 cdce_m_crc32_cb(void *arg, void *src, uint32_t count) 964 { 965 uint32_t *p_crc = arg; 966 967 *p_crc = crc32_raw(src, count, *p_crc); 968 return (0); 969 } 970 971 static uint32_t 972 cdce_m_crc32(struct mbuf *m, uint32_t src_offset, uint32_t src_len) 973 { 974 uint32_t crc = 0xFFFFFFFF; 975 976 (void)m_apply(m, src_offset, src_len, cdce_m_crc32_cb, &crc); 977 return (crc ^ 0xFFFFFFFF); 978 } 979 980 static void 981 cdce_init(struct usb_ether *ue) 982 { 983 struct cdce_softc *sc = uether_getsc(ue); 984 if_t ifp = uether_getifp(ue); 985 986 CDCE_LOCK_ASSERT(sc, MA_OWNED); 987 988 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 989 990 /* start interrupt transfer */ 991 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_RX]); 992 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]); 993 994 /* 995 * Stall data write direction, which depends on USB mode. 996 * 997 * Some USB host stacks (e.g. Mac OS X) don't clears stall 998 * bit as it should, so set it in our host mode only. 999 */ 1000 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) 1001 usbd_xfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]); 1002 1003 /* start data transfers */ 1004 cdce_start(ue); 1005 } 1006 1007 static void 1008 cdce_stop(struct usb_ether *ue) 1009 { 1010 struct cdce_softc *sc = uether_getsc(ue); 1011 if_t ifp = uether_getifp(ue); 1012 1013 CDCE_LOCK_ASSERT(sc, MA_OWNED); 1014 1015 if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); 1016 1017 /* 1018 * stop all the transfers, if not already stopped: 1019 */ 1020 usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_RX]); 1021 usbd_transfer_stop(sc->sc_xfer[CDCE_BULK_TX]); 1022 usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_RX]); 1023 usbd_transfer_stop(sc->sc_xfer[CDCE_INTR_TX]); 1024 } 1025 1026 static void 1027 cdce_setmulti(struct usb_ether *ue) 1028 { 1029 1030 cdce_set_filter(ue); 1031 } 1032 1033 static void 1034 cdce_setpromisc(struct usb_ether *ue) 1035 { 1036 1037 cdce_set_filter(ue); 1038 } 1039 1040 static void 1041 cdce_set_filter(struct usb_ether *ue) 1042 { 1043 struct cdce_softc *sc = uether_getsc(ue); 1044 if_t ifp = uether_getifp(ue); 1045 struct usb_device_request req; 1046 uint16_t value; 1047 1048 value = CDC_PACKET_TYPE_DIRECTED | CDC_PACKET_TYPE_BROADCAST; 1049 if (if_getflags(ifp) & IFF_PROMISC) 1050 value |= CDC_PACKET_TYPE_PROMISC; 1051 if (if_getflags(ifp) & IFF_ALLMULTI) 1052 value |= CDC_PACKET_TYPE_ALL_MULTICAST; 1053 1054 req.bmRequestType = UT_CLASS | UT_INTERFACE; 1055 req.bRequest = CDC_SET_ETHERNET_PACKET_FILTER; 1056 USETW(req.wValue, value); 1057 req.wIndex[0] = sc->sc_ifaces_index[1]; 1058 req.wIndex[1] = 0; 1059 USETW(req.wLength, 0); 1060 1061 /* 1062 * Function below will drop the sc mutex. 1063 * We can do that since we're called from a separate task, 1064 * that simply wraps the setpromisc/setmulti methods. 1065 */ 1066 usbd_do_request(sc->sc_ue.ue_udev, &sc->sc_mtx, &req, NULL); 1067 } 1068 1069 static int 1070 cdce_suspend(device_t dev) 1071 { 1072 device_printf(dev, "Suspending\n"); 1073 return (0); 1074 } 1075 1076 static int 1077 cdce_resume(device_t dev) 1078 { 1079 device_printf(dev, "Resuming\n"); 1080 return (0); 1081 } 1082 1083 static void 1084 cdce_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 1085 { 1086 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1087 struct mbuf *m; 1088 uint8_t x; 1089 int actlen; 1090 int aframes; 1091 int len; 1092 1093 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 1094 1095 switch (USB_GET_STATE(xfer)) { 1096 case USB_ST_TRANSFERRED: 1097 1098 DPRINTF("received %u bytes in %u frames\n", actlen, aframes); 1099 1100 for (x = 0; x != aframes; x++) { 1101 m = sc->sc_rx_buf[x]; 1102 sc->sc_rx_buf[x] = NULL; 1103 len = usbd_xfer_frame_len(xfer, x); 1104 1105 /* Strip off CRC added by Zaurus, if any */ 1106 if ((sc->sc_flags & CDCE_FLAG_ZAURUS) && len >= 14) 1107 len -= 4; 1108 1109 if (len < (int)sizeof(struct ether_header)) { 1110 m_freem(m); 1111 continue; 1112 } 1113 /* queue up mbuf */ 1114 uether_rxmbuf(&sc->sc_ue, m, len); 1115 } 1116 1117 /* FALLTHROUGH */ 1118 case USB_ST_SETUP: 1119 /* 1120 * TODO: Implement support for multi frame transfers, 1121 * when the USB hardware supports it. 1122 */ 1123 for (x = 0; x != 1; x++) { 1124 if (sc->sc_rx_buf[x] == NULL) { 1125 m = uether_newbuf(); 1126 if (m == NULL) 1127 goto tr_stall; 1128 sc->sc_rx_buf[x] = m; 1129 } else { 1130 m = sc->sc_rx_buf[x]; 1131 } 1132 1133 usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len); 1134 } 1135 /* set number of frames and start hardware */ 1136 usbd_xfer_set_frames(xfer, x); 1137 usbd_transfer_submit(xfer); 1138 /* flush any received frames */ 1139 uether_rxflush(&sc->sc_ue); 1140 break; 1141 1142 default: /* Error */ 1143 DPRINTF("error = %s\n", 1144 usbd_errstr(error)); 1145 1146 if (error != USB_ERR_CANCELLED) { 1147 tr_stall: 1148 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 1149 /* try to clear stall first */ 1150 usbd_xfer_set_stall(xfer); 1151 usbd_xfer_set_frames(xfer, 0); 1152 usbd_transfer_submit(xfer); 1153 } 1154 break; 1155 } 1156 1157 /* need to free the RX-mbufs when we are cancelled */ 1158 cdce_free_queue(sc->sc_rx_buf, CDCE_FRAMES_MAX); 1159 break; 1160 } 1161 } 1162 1163 static void 1164 cdce_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) 1165 { 1166 u_char buf[CDCE_IND_SIZE_MAX]; 1167 struct usb_cdc_notification ucn; 1168 struct cdce_softc *sc; 1169 if_t ifp; 1170 struct usb_page_cache *pc; 1171 int off, actlen; 1172 uint32_t downrate, uprate; 1173 1174 sc = usbd_xfer_softc(xfer); 1175 ifp = uether_getifp(&sc->sc_ue); 1176 pc = usbd_xfer_get_frame(xfer, 0); 1177 1178 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 1179 1180 switch (USB_GET_STATE(xfer)) { 1181 case USB_ST_TRANSFERRED: 1182 if (USB_DEBUG_VAR) 1183 usbd_copy_out(pc, 0, buf, MIN(actlen, sizeof buf)); 1184 DPRINTF("Received %d bytes: %*D\n", actlen, 1185 (int)MIN(actlen, sizeof buf), buf, ""); 1186 1187 off = 0; 1188 while (actlen - off >= UCDC_NOTIFICATION_LENGTH) { 1189 usbd_copy_out(pc, off, &ucn, UCDC_NOTIFICATION_LENGTH); 1190 1191 do { 1192 if (ucn.bmRequestType != 0xa1) 1193 break; 1194 1195 switch (ucn.bNotification) { 1196 case UCDC_N_NETWORK_CONNECTION: 1197 DPRINTF("changing link state: %d\n", 1198 UGETW(ucn.wValue)); 1199 if_link_state_change(ifp, 1200 UGETW(ucn.wValue) ? LINK_STATE_UP : 1201 LINK_STATE_DOWN); 1202 break; 1203 1204 case UCDC_N_CONNECTION_SPEED_CHANGE: 1205 if (UGETW(ucn.wLength) != 8) 1206 break; 1207 1208 usbd_copy_out(pc, off + 1209 UCDC_NOTIFICATION_LENGTH, 1210 &ucn.data, UGETW(ucn.wLength)); 1211 downrate = UGETDW(ucn.data); 1212 uprate = UGETDW(ucn.data); 1213 if (downrate != uprate) 1214 break; 1215 1216 /* set rate */ 1217 DPRINTF("changing baudrate: %u\n", 1218 downrate); 1219 if_setbaudrate(ifp, downrate); 1220 break; 1221 1222 default: 1223 break; 1224 } 1225 } while (0); 1226 1227 off += UCDC_NOTIFICATION_LENGTH + UGETW(ucn.wLength); 1228 } 1229 1230 /* FALLTHROUGH */ 1231 case USB_ST_SETUP: 1232 tr_setup: 1233 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 1234 usbd_transfer_submit(xfer); 1235 break; 1236 1237 default: /* Error */ 1238 if (error != USB_ERR_CANCELLED) { 1239 /* start clear stall */ 1240 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) 1241 usbd_xfer_set_stall(xfer); 1242 goto tr_setup; 1243 } 1244 break; 1245 } 1246 } 1247 1248 static void 1249 cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error) 1250 { 1251 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1252 struct usb_cdc_notification req; 1253 struct usb_page_cache *pc; 1254 uint32_t speed; 1255 int actlen; 1256 1257 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 1258 1259 switch (USB_GET_STATE(xfer)) { 1260 case USB_ST_TRANSFERRED: 1261 1262 DPRINTF("Transferred %d bytes\n", actlen); 1263 1264 switch (sc->sc_notify_state) { 1265 case CDCE_NOTIFY_NETWORK_CONNECTION: 1266 sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE; 1267 break; 1268 case CDCE_NOTIFY_SPEED_CHANGE: 1269 sc->sc_notify_state = CDCE_NOTIFY_DONE; 1270 break; 1271 default: 1272 break; 1273 } 1274 1275 /* FALLTHROUGH */ 1276 case USB_ST_SETUP: 1277 tr_setup: 1278 /* 1279 * Inform host about connection. Required according to USB CDC 1280 * specification and communicating to Mac OS X USB host stack. 1281 * Some of the values seems ignored by Mac OS X though. 1282 */ 1283 if (sc->sc_notify_state == CDCE_NOTIFY_NETWORK_CONNECTION) { 1284 req.bmRequestType = UCDC_NOTIFICATION; 1285 req.bNotification = UCDC_N_NETWORK_CONNECTION; 1286 req.wIndex[0] = sc->sc_ifaces_index[1]; 1287 req.wIndex[1] = 0; 1288 USETW(req.wValue, 1); /* Connected */ 1289 USETW(req.wLength, 0); 1290 1291 pc = usbd_xfer_get_frame(xfer, 0); 1292 usbd_copy_in(pc, 0, &req, sizeof(req)); 1293 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 1294 usbd_xfer_set_frames(xfer, 1); 1295 usbd_transfer_submit(xfer); 1296 1297 } else if (sc->sc_notify_state == CDCE_NOTIFY_SPEED_CHANGE) { 1298 req.bmRequestType = UCDC_NOTIFICATION; 1299 req.bNotification = UCDC_N_CONNECTION_SPEED_CHANGE; 1300 req.wIndex[0] = sc->sc_ifaces_index[1]; 1301 req.wIndex[1] = 0; 1302 USETW(req.wValue, 0); 1303 USETW(req.wLength, 8); 1304 1305 /* Peak theoretical bulk trasfer rate in bits/s */ 1306 if (usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_FULL) 1307 speed = (13 * 512 * 8 * 1000 * 8); 1308 else 1309 speed = (19 * 64 * 1 * 1000 * 8); 1310 1311 USETDW(req.data + 0, speed); /* Upstream bit rate */ 1312 USETDW(req.data + 4, speed); /* Downstream bit rate */ 1313 1314 pc = usbd_xfer_get_frame(xfer, 0); 1315 usbd_copy_in(pc, 0, &req, sizeof(req)); 1316 usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); 1317 usbd_xfer_set_frames(xfer, 1); 1318 usbd_transfer_submit(xfer); 1319 } 1320 break; 1321 1322 default: /* Error */ 1323 if (error != USB_ERR_CANCELLED) { 1324 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 1325 /* start clear stall */ 1326 usbd_xfer_set_stall(xfer); 1327 } 1328 goto tr_setup; 1329 } 1330 break; 1331 } 1332 } 1333 1334 static int 1335 cdce_handle_request(device_t dev, 1336 const void *preq, void **pptr, uint16_t *plen, 1337 uint16_t offset, uint8_t *pstate) 1338 { 1339 struct cdce_softc *sc = device_get_softc(dev); 1340 const struct usb_device_request *req = preq; 1341 uint8_t is_complete = *pstate; 1342 1343 /* 1344 * When Mac OS X resumes after suspending it expects 1345 * to be notified again after this request. 1346 */ 1347 if (req->bmRequestType == UT_WRITE_CLASS_INTERFACE && \ 1348 req->bRequest == UCDC_NCM_SET_ETHERNET_PACKET_FILTER) { 1349 if (is_complete == 1) { 1350 mtx_lock(&sc->sc_mtx); 1351 sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE; 1352 usbd_transfer_start(sc->sc_xfer[CDCE_INTR_TX]); 1353 mtx_unlock(&sc->sc_mtx); 1354 } 1355 1356 return (0); 1357 } 1358 1359 return (ENXIO); /* use builtin handler */ 1360 } 1361 1362 #if CDCE_HAVE_NCM 1363 static void 1364 cdce_ncm_tx_zero(struct usb_page_cache *pc, 1365 uint32_t start, uint32_t end) 1366 { 1367 if (start >= CDCE_NCM_TX_MAXLEN) 1368 return; 1369 if (end > CDCE_NCM_TX_MAXLEN) 1370 end = CDCE_NCM_TX_MAXLEN; 1371 1372 usbd_frame_zero(pc, start, end - start); 1373 } 1374 1375 static uint8_t 1376 cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uint8_t index) 1377 { 1378 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1379 if_t ifp = uether_getifp(&sc->sc_ue); 1380 struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, index); 1381 struct mbuf *m; 1382 uint32_t rem; 1383 uint32_t offset; 1384 uint32_t last_offset; 1385 uint16_t n; 1386 uint8_t retval; 1387 1388 usbd_xfer_set_frame_offset(xfer, index * CDCE_NCM_TX_MAXLEN, index); 1389 1390 offset = sizeof(sc->sc_ncm.hdr) + 1391 sizeof(sc->sc_ncm.dpt) + sizeof(sc->sc_ncm.dp); 1392 1393 /* Store last valid offset before alignment */ 1394 last_offset = offset; 1395 1396 /* Align offset */ 1397 offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder, 1398 offset, sc->sc_ncm.tx_modulus); 1399 1400 /* Zero pad */ 1401 cdce_ncm_tx_zero(pc, last_offset, offset); 1402 1403 /* buffer full */ 1404 retval = 2; 1405 1406 for (n = 0; n != sc->sc_ncm.tx_nframe; n++) { 1407 /* check if end of transmit buffer is reached */ 1408 1409 if (offset >= sc->sc_ncm.tx_max) 1410 break; 1411 1412 /* compute maximum buffer size */ 1413 1414 rem = sc->sc_ncm.tx_max - offset; 1415 1416 m = if_dequeue(ifp); 1417 1418 if (m == NULL) { 1419 /* buffer not full */ 1420 retval = 1; 1421 break; 1422 } 1423 1424 if (m->m_pkthdr.len > (int)rem) { 1425 if (n == 0) { 1426 /* The frame won't fit in our buffer */ 1427 DPRINTFN(1, "Frame too big to be transmitted!\n"); 1428 m_freem(m); 1429 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1430 n--; 1431 continue; 1432 } 1433 /* Wait till next buffer becomes ready */ 1434 if_sendq_prepend(ifp, m); 1435 break; 1436 } 1437 usbd_m_copy_in(pc, offset, m, 0, m->m_pkthdr.len); 1438 1439 USETW(sc->sc_ncm.dp[n].wFrameLength, m->m_pkthdr.len); 1440 USETW(sc->sc_ncm.dp[n].wFrameIndex, offset); 1441 1442 /* Update offset */ 1443 offset += m->m_pkthdr.len; 1444 1445 /* Store last valid offset before alignment */ 1446 last_offset = offset; 1447 1448 /* Align offset */ 1449 offset = CDCE_NCM_ALIGN(sc->sc_ncm.tx_remainder, 1450 offset, sc->sc_ncm.tx_modulus); 1451 1452 /* Zero pad */ 1453 cdce_ncm_tx_zero(pc, last_offset, offset); 1454 1455 /* 1456 * If there's a BPF listener, bounce a copy 1457 * of this frame to him: 1458 */ 1459 BPF_MTAP(ifp, m); 1460 1461 /* Free mbuf */ 1462 1463 m_freem(m); 1464 1465 /* Pre-increment interface counter */ 1466 1467 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 1468 } 1469 1470 if (n == 0) 1471 return (0); 1472 1473 rem = (sizeof(sc->sc_ncm.dpt) + (4 * n) + 4); 1474 1475 USETW(sc->sc_ncm.dpt.wLength, rem); 1476 1477 /* zero the rest of the data pointer entries */ 1478 for (; n != CDCE_NCM_SUBFRAMES_MAX; n++) { 1479 USETW(sc->sc_ncm.dp[n].wFrameLength, 0); 1480 USETW(sc->sc_ncm.dp[n].wFrameIndex, 0); 1481 } 1482 1483 offset = last_offset; 1484 1485 /* Align offset */ 1486 offset = CDCE_NCM_ALIGN(0, offset, CDCE_NCM_TX_MINLEN); 1487 1488 /* Optimise, save bandwidth and force short termination */ 1489 if (offset >= sc->sc_ncm.tx_max) 1490 offset = sc->sc_ncm.tx_max; 1491 else 1492 offset ++; 1493 1494 /* Zero pad */ 1495 cdce_ncm_tx_zero(pc, last_offset, offset); 1496 1497 /* set frame length */ 1498 usbd_xfer_set_frame_len(xfer, index, offset); 1499 1500 /* Fill out 16-bit header */ 1501 sc->sc_ncm.hdr.dwSignature[0] = 'N'; 1502 sc->sc_ncm.hdr.dwSignature[1] = 'C'; 1503 sc->sc_ncm.hdr.dwSignature[2] = 'M'; 1504 sc->sc_ncm.hdr.dwSignature[3] = 'H'; 1505 USETW(sc->sc_ncm.hdr.wHeaderLength, sizeof(sc->sc_ncm.hdr)); 1506 USETW(sc->sc_ncm.hdr.wBlockLength, offset); 1507 USETW(sc->sc_ncm.hdr.wSequence, sc->sc_ncm.tx_seq); 1508 USETW(sc->sc_ncm.hdr.wDptIndex, sizeof(sc->sc_ncm.hdr)); 1509 1510 sc->sc_ncm.tx_seq++; 1511 1512 /* Fill out 16-bit frame table header */ 1513 sc->sc_ncm.dpt.dwSignature[0] = 'N'; 1514 sc->sc_ncm.dpt.dwSignature[1] = 'C'; 1515 sc->sc_ncm.dpt.dwSignature[2] = 'M'; 1516 sc->sc_ncm.dpt.dwSignature[3] = '0'; 1517 USETW(sc->sc_ncm.dpt.wNextNdpIndex, 0); /* reserved */ 1518 1519 usbd_copy_in(pc, 0, &(sc->sc_ncm.hdr), sizeof(sc->sc_ncm.hdr)); 1520 usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr), &(sc->sc_ncm.dpt), 1521 sizeof(sc->sc_ncm.dpt)); 1522 usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr) + sizeof(sc->sc_ncm.dpt), 1523 &(sc->sc_ncm.dp), sizeof(sc->sc_ncm.dp)); 1524 return (retval); 1525 } 1526 1527 static void 1528 cdce_ncm_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 1529 { 1530 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1531 if_t ifp = uether_getifp(&sc->sc_ue); 1532 uint16_t x; 1533 uint8_t temp; 1534 int actlen; 1535 int aframes; 1536 1537 switch (USB_GET_STATE(xfer)) { 1538 case USB_ST_TRANSFERRED: 1539 1540 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 1541 1542 DPRINTFN(10, "transfer complete: " 1543 "%u bytes in %u frames\n", actlen, aframes); 1544 1545 case USB_ST_SETUP: 1546 for (x = 0; x != CDCE_NCM_TX_FRAMES_MAX; x++) { 1547 temp = cdce_ncm_fill_tx_frames(xfer, x); 1548 if (temp == 0) 1549 break; 1550 if (temp == 1) { 1551 x++; 1552 break; 1553 } 1554 } 1555 1556 if (x != 0) { 1557 #ifdef USB_DEBUG 1558 usbd_xfer_set_interval(xfer, cdce_tx_interval); 1559 #endif 1560 usbd_xfer_set_frames(xfer, x); 1561 usbd_transfer_submit(xfer); 1562 } 1563 break; 1564 1565 default: /* Error */ 1566 DPRINTFN(10, "Transfer error: %s\n", 1567 usbd_errstr(error)); 1568 1569 /* update error counter */ 1570 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1571 1572 if (error != USB_ERR_CANCELLED) { 1573 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 1574 /* try to clear stall first */ 1575 usbd_xfer_set_stall(xfer); 1576 usbd_xfer_set_frames(xfer, 0); 1577 usbd_transfer_submit(xfer); 1578 } 1579 } 1580 break; 1581 } 1582 } 1583 1584 static void 1585 cdce_ncm_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 1586 { 1587 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1588 struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0); 1589 if_t ifp = uether_getifp(&sc->sc_ue); 1590 struct mbuf *m; 1591 int sumdata __usbdebug_used; 1592 int sumlen; 1593 int actlen; 1594 int aframes; 1595 int temp; 1596 int nframes; 1597 int x; 1598 int offset; 1599 1600 switch (USB_GET_STATE(xfer)) { 1601 case USB_ST_TRANSFERRED: 1602 1603 usbd_xfer_status(xfer, &actlen, &sumlen, &aframes, NULL); 1604 1605 DPRINTFN(1, "received %u bytes in %u frames\n", 1606 actlen, aframes); 1607 1608 if (actlen < (int)(sizeof(sc->sc_ncm.hdr) + 1609 sizeof(sc->sc_ncm.dpt))) { 1610 DPRINTFN(1, "frame too short\n"); 1611 goto tr_setup; 1612 } 1613 usbd_copy_out(pc, 0, &(sc->sc_ncm.hdr), 1614 sizeof(sc->sc_ncm.hdr)); 1615 1616 if ((sc->sc_ncm.hdr.dwSignature[0] != 'N') || 1617 (sc->sc_ncm.hdr.dwSignature[1] != 'C') || 1618 (sc->sc_ncm.hdr.dwSignature[2] != 'M') || 1619 (sc->sc_ncm.hdr.dwSignature[3] != 'H')) { 1620 DPRINTFN(1, "invalid HDR signature: " 1621 "0x%02x:0x%02x:0x%02x:0x%02x\n", 1622 sc->sc_ncm.hdr.dwSignature[0], 1623 sc->sc_ncm.hdr.dwSignature[1], 1624 sc->sc_ncm.hdr.dwSignature[2], 1625 sc->sc_ncm.hdr.dwSignature[3]); 1626 goto tr_stall; 1627 } 1628 temp = UGETW(sc->sc_ncm.hdr.wBlockLength); 1629 if (temp > sumlen) { 1630 DPRINTFN(1, "unsupported block length %u/%u\n", 1631 temp, sumlen); 1632 goto tr_stall; 1633 } 1634 temp = UGETW(sc->sc_ncm.hdr.wDptIndex); 1635 if ((int)(temp + sizeof(sc->sc_ncm.dpt)) > actlen) { 1636 DPRINTFN(1, "invalid DPT index: 0x%04x\n", temp); 1637 goto tr_stall; 1638 } 1639 usbd_copy_out(pc, temp, &(sc->sc_ncm.dpt), 1640 sizeof(sc->sc_ncm.dpt)); 1641 1642 if ((sc->sc_ncm.dpt.dwSignature[0] != 'N') || 1643 (sc->sc_ncm.dpt.dwSignature[1] != 'C') || 1644 (sc->sc_ncm.dpt.dwSignature[2] != 'M') || 1645 (sc->sc_ncm.dpt.dwSignature[3] != '0')) { 1646 DPRINTFN(1, "invalid DPT signature" 1647 "0x%02x:0x%02x:0x%02x:0x%02x\n", 1648 sc->sc_ncm.dpt.dwSignature[0], 1649 sc->sc_ncm.dpt.dwSignature[1], 1650 sc->sc_ncm.dpt.dwSignature[2], 1651 sc->sc_ncm.dpt.dwSignature[3]); 1652 goto tr_stall; 1653 } 1654 nframes = UGETW(sc->sc_ncm.dpt.wLength) / 4; 1655 1656 /* Subtract size of header and last zero padded entry */ 1657 if (nframes >= (2 + 1)) 1658 nframes -= (2 + 1); 1659 else 1660 nframes = 0; 1661 1662 DPRINTFN(1, "nframes = %u\n", nframes); 1663 1664 temp += sizeof(sc->sc_ncm.dpt); 1665 1666 if ((temp + (4 * nframes)) > actlen) 1667 goto tr_stall; 1668 1669 if (nframes > CDCE_NCM_SUBFRAMES_MAX) { 1670 DPRINTFN(1, "Truncating number of frames from %u to %u\n", 1671 nframes, CDCE_NCM_SUBFRAMES_MAX); 1672 nframes = CDCE_NCM_SUBFRAMES_MAX; 1673 } 1674 usbd_copy_out(pc, temp, &(sc->sc_ncm.dp), (4 * nframes)); 1675 1676 sumdata = 0; 1677 1678 for (x = 0; x != nframes; x++) { 1679 offset = UGETW(sc->sc_ncm.dp[x].wFrameIndex); 1680 temp = UGETW(sc->sc_ncm.dp[x].wFrameLength); 1681 1682 if ((offset == 0) || 1683 (temp < (int)sizeof(struct ether_header)) || 1684 (temp > (MCLBYTES - ETHER_ALIGN))) { 1685 DPRINTFN(1, "NULL frame detected at %d\n", x); 1686 m = NULL; 1687 /* silently ignore this frame */ 1688 continue; 1689 } else if ((offset + temp) > actlen) { 1690 DPRINTFN(1, "invalid frame " 1691 "detected at %d\n", x); 1692 m = NULL; 1693 /* silently ignore this frame */ 1694 continue; 1695 } else if (temp > (int)(MHLEN - ETHER_ALIGN)) { 1696 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1697 } else { 1698 m = m_gethdr(M_NOWAIT, MT_DATA); 1699 } 1700 1701 DPRINTFN(16, "frame %u, offset = %u, length = %u \n", 1702 x, offset, temp); 1703 1704 /* check if we have a buffer */ 1705 if (m) { 1706 m->m_len = m->m_pkthdr.len = temp + ETHER_ALIGN; 1707 m_adj(m, ETHER_ALIGN); 1708 1709 usbd_copy_out(pc, offset, m->m_data, temp); 1710 1711 /* enqueue */ 1712 uether_rxmbuf(&sc->sc_ue, m, temp); 1713 1714 sumdata += temp; 1715 } else { 1716 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1717 } 1718 } 1719 1720 DPRINTFN(1, "Efficiency: %u/%u bytes\n", sumdata, actlen); 1721 1722 case USB_ST_SETUP: 1723 tr_setup: 1724 usbd_xfer_set_frame_len(xfer, 0, sc->sc_ncm.rx_max); 1725 usbd_xfer_set_frames(xfer, 1); 1726 usbd_transfer_submit(xfer); 1727 uether_rxflush(&sc->sc_ue); /* must be last */ 1728 break; 1729 1730 default: /* Error */ 1731 DPRINTFN(1, "error = %s\n", 1732 usbd_errstr(error)); 1733 1734 if (error != USB_ERR_CANCELLED) { 1735 tr_stall: 1736 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 1737 /* try to clear stall first */ 1738 usbd_xfer_set_stall(xfer); 1739 usbd_xfer_set_frames(xfer, 0); 1740 usbd_transfer_submit(xfer); 1741 } 1742 } 1743 break; 1744 } 1745 } 1746 #endif 1747