if_cdce.c (196492) | if_cdce.c (197563) |
---|---|
1/* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> 5 * Copyright (c) 2003-2005 Craig Boston 6 * Copyright (c) 2004 Daniel Hartmeier 7 * Copyright (c) 2009 Hans Petter Selasky 8 * All rights reserved. --- 26 unchanged lines hidden (view full) --- 35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * USB Communication Device Class (Ethernet Networking Control Model) 40 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf 41 */ 42 | 1/* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> 5 * Copyright (c) 2003-2005 Craig Boston 6 * Copyright (c) 2004 Daniel Hartmeier 7 * Copyright (c) 2009 Hans Petter Selasky 8 * All rights reserved. --- 26 unchanged lines hidden (view full) --- 35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * USB Communication Device Class (Ethernet Networking Control Model) 40 * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf 41 */ 42 |
43/* 44 * USB Network Control Model (NCM) 45 * http://www.usb.org/developers/devclass_docs/NCM10.zip 46 */ 47 |
|
43#include <sys/cdefs.h> | 48#include <sys/cdefs.h> |
44__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_cdce.c 196492 2009-08-24 05:00:33Z alfred $"); | 49__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_cdce.c 197563 2009-09-28 07:53:55Z thompsa $"); |
45 46#include <sys/stdint.h> 47#include <sys/stddef.h> 48#include <sys/param.h> 49#include <sys/queue.h> 50#include <sys/types.h> 51#include <sys/systm.h> 52#include <sys/kernel.h> --- 31 unchanged lines hidden (view full) --- 84static device_resume_t cdce_resume; 85static usb_handle_request_t cdce_handle_request; 86 87static usb_callback_t cdce_bulk_write_callback; 88static usb_callback_t cdce_bulk_read_callback; 89static usb_callback_t cdce_intr_read_callback; 90static usb_callback_t cdce_intr_write_callback; 91 | 50 51#include <sys/stdint.h> 52#include <sys/stddef.h> 53#include <sys/param.h> 54#include <sys/queue.h> 55#include <sys/types.h> 56#include <sys/systm.h> 57#include <sys/kernel.h> --- 31 unchanged lines hidden (view full) --- 89static device_resume_t cdce_resume; 90static usb_handle_request_t cdce_handle_request; 91 92static usb_callback_t cdce_bulk_write_callback; 93static usb_callback_t cdce_bulk_read_callback; 94static usb_callback_t cdce_intr_read_callback; 95static usb_callback_t cdce_intr_write_callback; 96 |
97#if CDCE_HAVE_NCM 98static usb_callback_t cdce_ncm_bulk_write_callback; 99static usb_callback_t cdce_ncm_bulk_read_callback; 100#endif 101 |
|
92static uether_fn_t cdce_attach_post; 93static uether_fn_t cdce_init; 94static uether_fn_t cdce_stop; 95static uether_fn_t cdce_start; 96static uether_fn_t cdce_setmulti; 97static uether_fn_t cdce_setpromisc; 98 99static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t); --- 54 unchanged lines hidden (view full) --- 154 .bufsize = CDCE_IND_SIZE_MAX, 155 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 156 .callback = cdce_intr_write_callback, 157 .timeout = 10000, /* 10 seconds */ 158 .usb_mode = USB_MODE_DEVICE, 159 }, 160}; 161 | 102static uether_fn_t cdce_attach_post; 103static uether_fn_t cdce_init; 104static uether_fn_t cdce_stop; 105static uether_fn_t cdce_start; 106static uether_fn_t cdce_setmulti; 107static uether_fn_t cdce_setpromisc; 108 109static uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t); --- 54 unchanged lines hidden (view full) --- 164 .bufsize = CDCE_IND_SIZE_MAX, 165 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 166 .callback = cdce_intr_write_callback, 167 .timeout = 10000, /* 10 seconds */ 168 .usb_mode = USB_MODE_DEVICE, 169 }, 170}; 171 |
172#if CDCE_HAVE_NCM 173static const struct usb_config cdce_ncm_config[CDCE_N_TRANSFER] = { 174 175 [CDCE_BULK_RX] = { 176 .type = UE_BULK, 177 .endpoint = UE_ADDR_ANY, 178 .direction = UE_DIR_RX, 179 .if_index = 0, 180 .frames = CDCE_NCM_RX_FRAMES_MAX, 181 .bufsize = (CDCE_NCM_RX_FRAMES_MAX * CDCE_NCM_RX_MAXLEN), 182 .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,}, 183 .callback = cdce_ncm_bulk_read_callback, 184 .timeout = 0, /* no timeout */ 185 .usb_mode = USB_MODE_DUAL, /* both modes */ 186 }, 187 188 [CDCE_BULK_TX] = { 189 .type = UE_BULK, 190 .endpoint = UE_ADDR_ANY, 191 .direction = UE_DIR_TX, 192 .if_index = 0, 193 .frames = CDCE_NCM_TX_FRAMES_MAX, 194 .bufsize = (CDCE_NCM_TX_FRAMES_MAX * CDCE_NCM_TX_MAXLEN), 195 .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 196 .callback = cdce_ncm_bulk_write_callback, 197 .timeout = 10000, /* 10 seconds */ 198 .usb_mode = USB_MODE_DUAL, /* both modes */ 199 }, 200 201 [CDCE_INTR_RX] = { 202 .type = UE_INTERRUPT, 203 .endpoint = UE_ADDR_ANY, 204 .direction = UE_DIR_RX, 205 .if_index = 1, 206 .bufsize = CDCE_IND_SIZE_MAX, 207 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, 208 .callback = cdce_intr_read_callback, 209 .timeout = 0, 210 .usb_mode = USB_MODE_HOST, 211 }, 212 213 [CDCE_INTR_TX] = { 214 .type = UE_INTERRUPT, 215 .endpoint = UE_ADDR_ANY, 216 .direction = UE_DIR_TX, 217 .if_index = 1, 218 .bufsize = CDCE_IND_SIZE_MAX, 219 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 220 .callback = cdce_intr_write_callback, 221 .timeout = 10000, /* 10 seconds */ 222 .usb_mode = USB_MODE_DEVICE, 223 }, 224}; 225#endif 226 |
|
162static device_method_t cdce_methods[] = { 163 /* USB interface */ 164 DEVMETHOD(usb_handle_request, cdce_handle_request), 165 166 /* Device interface */ 167 DEVMETHOD(device_probe, cdce_probe), 168 DEVMETHOD(device_attach, cdce_attach), 169 DEVMETHOD(device_detach, cdce_detach), --- 38 unchanged lines hidden (view full) --- 208 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)}, 209 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 210 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 211 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 212 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 213 214 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)}, 215 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)}, | 227static device_method_t cdce_methods[] = { 228 /* USB interface */ 229 DEVMETHOD(usb_handle_request, cdce_handle_request), 230 231 /* Device interface */ 232 DEVMETHOD(device_probe, cdce_probe), 233 DEVMETHOD(device_attach, cdce_attach), 234 DEVMETHOD(device_detach, cdce_detach), --- 38 unchanged lines hidden (view full) --- 273 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)}, 274 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 275 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 276 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 277 {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 278 279 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)}, 280 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)}, |
281 {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_NETWORK_CONTROL_MODEL, 0)}, |
|
216}; 217 | 282}; 283 |
284#if CDCE_HAVE_NCM 285/*------------------------------------------------------------------------* 286 * cdce_ncm_init 287 * 288 * Return values: 289 * 0: Success 290 * Else: Failure 291 *------------------------------------------------------------------------*/ 292static uint8_t 293cdce_ncm_init(struct cdce_softc *sc) 294{ 295 struct usb_ncm_parameters temp; 296 struct usb_device_request req; 297 uDWord value; 298 int err; 299 300 req.bmRequestType = UT_READ_CLASS_INTERFACE; 301 req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS; 302 USETW(req.wValue, 0); 303 req.wIndex[0] = sc->sc_ifaces_index[1]; 304 req.wIndex[1] = 0; 305 USETW(req.wLength, sizeof(temp)); 306 307 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 308 &temp, 0, NULL, 1000 /* ms */); 309 if (err) 310 return (1); 311 312 /* Read correct set of parameters according to device mode */ 313 314 if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) { 315 sc->sc_ncm.rx_max = UGETW(temp.dwNtbInMaxSize); 316 sc->sc_ncm.tx_max = UGETW(temp.dwNtbOutMaxSize); 317 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder); 318 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor); 319 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment); 320 } else { 321 sc->sc_ncm.rx_max = UGETW(temp.dwNtbOutMaxSize); 322 sc->sc_ncm.tx_max = UGETW(temp.dwNtbInMaxSize); 323 sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder); 324 sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor); 325 sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment); 326 } 327 328 /* Verify maximum receive length */ 329 330 if (err || (sc->sc_ncm.rx_max < 32) || 331 (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) { 332 DPRINTFN(1, "Using default maximum receive length\n"); 333 sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN; 334 } 335 336 /* Verify maximum transmit length */ 337 338 if (err || (sc->sc_ncm.tx_max < 32) || 339 (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) { 340 DPRINTFN(1, "Using default maximum transmit length\n"); 341 sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN; 342 } 343 344 /* 345 * Verify that the structure alignment is: 346 * - power of two 347 * - not greater than the maximum transmit length 348 * - not less than four bytes 349 */ 350 if (err || (sc->sc_ncm.tx_struct_align < 4) || 351 (sc->sc_ncm.tx_struct_align != 352 ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) || 353 (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) { 354 DPRINTFN(1, "Using default other alignment: 4 bytes\n"); 355 sc->sc_ncm.tx_struct_align = 4; 356 } 357 358 /* 359 * Verify that the payload alignment is: 360 * - power of two 361 * - not greater than the maximum transmit length 362 * - not less than four bytes 363 */ 364 if (err || (sc->sc_ncm.tx_modulus < 4) || 365 (sc->sc_ncm.tx_modulus != 366 ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) || 367 (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) { 368 DPRINTFN(1, "Using default transmit modulus: 4 bytes\n"); 369 sc->sc_ncm.tx_modulus = 4; 370 } 371 372 /* Verify that the payload remainder */ 373 374 if (err || (sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) { 375 DPRINTFN(1, "Using default transmit remainder: 0 bytes\n"); 376 sc->sc_ncm.tx_remainder = 0; 377 } 378 379 /* Additional configuration, will fail in device side mode, which is OK. */ 380 381 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 382 req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE; 383 USETW(req.wValue, 0); 384 req.wIndex[0] = sc->sc_ifaces_index[1]; 385 req.wIndex[1] = 0; 386 USETW(req.wLength, 4); 387 USETDW(value, sc->sc_ncm.rx_max); 388 389 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 390 &value, 0, NULL, 1000 /* ms */); 391 if (err) { 392 DPRINTFN(1, "Setting input size " 393 "to %u failed.\n", sc->sc_ncm.rx_max); 394 } 395 396 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 397 req.bRequest = UCDC_NCM_SET_CRC_MODE; 398 USETW(req.wValue, 0); /* no CRC */ 399 req.wIndex[0] = sc->sc_ifaces_index[1]; 400 req.wIndex[1] = 0; 401 USETW(req.wLength, 0); 402 403 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 404 NULL, 0, NULL, 1000 /* ms */); 405 if (err) { 406 DPRINTFN(1, "Setting CRC mode to off failed.\n"); 407 } 408 409 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 410 req.bRequest = UCDC_NCM_SET_NTB_FORMAT; 411 USETW(req.wValue, 0); /* NTB-16 */ 412 req.wIndex[0] = sc->sc_ifaces_index[1]; 413 req.wIndex[1] = 0; 414 USETW(req.wLength, 0); 415 416 err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req, 417 NULL, 0, NULL, 1000 /* ms */); 418 if (err) { 419 DPRINTFN(1, "Setting NTB format to 16-bit failed.\n"); 420 } 421 422 return (0); /* success */ 423} 424#endif 425 |
|
218static int 219cdce_probe(device_t dev) 220{ 221 struct usb_attach_arg *uaa = device_get_ivars(dev); 222 223 return (usbd_lookup_id_by_uaa(cdce_devs, sizeof(cdce_devs), uaa)); 224} 225 --- 9 unchanged lines hidden (view full) --- 235{ 236 struct cdce_softc *sc = device_get_softc(dev); 237 struct usb_ether *ue = &sc->sc_ue; 238 struct usb_attach_arg *uaa = device_get_ivars(dev); 239 struct usb_interface *iface; 240 const struct usb_cdc_union_descriptor *ud; 241 const struct usb_interface_descriptor *id; 242 const struct usb_cdc_ethernet_descriptor *ued; | 426static int 427cdce_probe(device_t dev) 428{ 429 struct usb_attach_arg *uaa = device_get_ivars(dev); 430 431 return (usbd_lookup_id_by_uaa(cdce_devs, sizeof(cdce_devs), uaa)); 432} 433 --- 9 unchanged lines hidden (view full) --- 443{ 444 struct cdce_softc *sc = device_get_softc(dev); 445 struct usb_ether *ue = &sc->sc_ue; 446 struct usb_attach_arg *uaa = device_get_ivars(dev); 447 struct usb_interface *iface; 448 const struct usb_cdc_union_descriptor *ud; 449 const struct usb_interface_descriptor *id; 450 const struct usb_cdc_ethernet_descriptor *ued; |
451 const struct usb_config *pcfg; |
|
243 int error; 244 uint8_t i; | 452 int error; 453 uint8_t i; |
454 uint8_t data_iface_no; |
|
245 char eaddr_str[5 * ETHER_ADDR_LEN]; /* approx */ 246 247 sc->sc_flags = USB_GET_DRIVER_INFO(uaa); | 455 char eaddr_str[5 * ETHER_ADDR_LEN]; /* approx */ 456 457 sc->sc_flags = USB_GET_DRIVER_INFO(uaa); |
458 sc->sc_ue.ue_udev = uaa->device; |
|
248 249 device_set_usb_desc(dev); 250 251 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 252 | 459 460 device_set_usb_desc(dev); 461 462 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 463 |
253 if (sc->sc_flags & CDCE_FLAG_NO_UNION) { 254 sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex; 255 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 256 sc->sc_data_iface_no = 0; /* not used */ 257 goto alloc_transfers; 258 } | |
259 ud = usbd_find_descriptor 260 (uaa->device, NULL, uaa->info.bIfaceIndex, 261 UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_UNION, 0 - 1); 262 | 464 ud = usbd_find_descriptor 465 (uaa->device, NULL, uaa->info.bIfaceIndex, 466 UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_UNION, 0 - 1); 467 |
263 if ((ud == NULL) || (ud->bLength < sizeof(*ud))) { 264 device_printf(dev, "no union descriptor!\n"); 265 goto detach; | 468 if ((ud == NULL) || (ud->bLength < sizeof(*ud)) || 469 (sc->sc_flags & CDCE_FLAG_NO_UNION)) { 470 DPRINTFN(1, "No union descriptor!\n"); 471 sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex; 472 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 473 goto alloc_transfers; |
266 } | 474 } |
267 sc->sc_data_iface_no = ud->bSlaveInterface[0]; | 475 data_iface_no = ud->bSlaveInterface[0]; |
268 269 for (i = 0;; i++) { 270 271 iface = usbd_get_iface(uaa->device, i); 272 273 if (iface) { 274 275 id = usbd_get_interface_descriptor(iface); 276 | 476 477 for (i = 0;; i++) { 478 479 iface = usbd_get_iface(uaa->device, i); 480 481 if (iface) { 482 483 id = usbd_get_interface_descriptor(iface); 484 |
277 if (id && (id->bInterfaceNumber == 278 sc->sc_data_iface_no)) { | 485 if (id && (id->bInterfaceNumber == data_iface_no)) { |
279 sc->sc_ifaces_index[0] = i; 280 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 281 usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); 282 break; 283 } 284 } else { 285 device_printf(dev, "no data interface found!\n"); 286 goto detach; --- 20 unchanged lines hidden (view full) --- 307 * Some devices, most notably cable modems, include interface 308 * settings that have no IN or OUT endpoint, therefore loop 309 * through the list of all available interface settings 310 * looking for one with both IN and OUT endpoints. 311 */ 312 313alloc_transfers: 314 | 486 sc->sc_ifaces_index[0] = i; 487 sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 488 usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); 489 break; 490 } 491 } else { 492 device_printf(dev, "no data interface found!\n"); 493 goto detach; --- 20 unchanged lines hidden (view full) --- 514 * Some devices, most notably cable modems, include interface 515 * settings that have no IN or OUT endpoint, therefore loop 516 * through the list of all available interface settings 517 * looking for one with both IN and OUT endpoints. 518 */ 519 520alloc_transfers: 521 |
522 pcfg = cdce_config; /* Default Configuration */ 523 |
|
315 for (i = 0; i != 32; i++) { 316 | 524 for (i = 0; i != 32; i++) { 525 |
317 error = usbd_set_alt_interface_index 318 (uaa->device, sc->sc_ifaces_index[0], i); | 526 error = usbd_set_alt_interface_index(uaa->device, 527 sc->sc_ifaces_index[0], i); 528 if (error) 529 break; 530#if CDCE_HAVE_NCM 531 if ((i == 0) && (cdce_ncm_init(sc) == 0)) 532 pcfg = cdce_ncm_config; 533#endif 534 error = usbd_transfer_setup(uaa->device, 535 sc->sc_ifaces_index, sc->sc_xfer, 536 pcfg, CDCE_N_TRANSFER, sc, &sc->sc_mtx); |
319 | 537 |
320 if (error) { 321 device_printf(dev, "no valid alternate " 322 "setting found!\n"); 323 goto detach; 324 } 325 error = usbd_transfer_setup 326 (uaa->device, sc->sc_ifaces_index, 327 sc->sc_xfer, cdce_config, CDCE_N_TRANSFER, 328 sc, &sc->sc_mtx); 329 330 if (error == 0) { | 538 if (error == 0) |
331 break; | 539 break; |
332 } | |
333 } 334 | 540 } 541 |
542 if (error || (i == 32)) { 543 device_printf(dev, "No valid alternate " 544 "setting found!\n"); 545 goto detach; 546 } 547 |
|
335 ued = usbd_find_descriptor 336 (uaa->device, NULL, uaa->info.bIfaceIndex, 337 UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_ENF, 0 - 1); 338 339 if ((ued == NULL) || (ued->bLength < sizeof(*ued))) { 340 error = USB_ERR_INVAL; 341 } else { 342 error = usbd_req_get_string_any(uaa->device, NULL, --- 420 unchanged lines hidden (view full) --- 763 764static int 765cdce_handle_request(device_t dev, 766 const void *req, void **pptr, uint16_t *plen, 767 uint16_t offset, uint8_t *pstate) 768{ 769 return (ENXIO); /* use builtin handler */ 770} | 548 ued = usbd_find_descriptor 549 (uaa->device, NULL, uaa->info.bIfaceIndex, 550 UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_ENF, 0 - 1); 551 552 if ((ued == NULL) || (ued->bLength < sizeof(*ued))) { 553 error = USB_ERR_INVAL; 554 } else { 555 error = usbd_req_get_string_any(uaa->device, NULL, --- 420 unchanged lines hidden (view full) --- 976 977static int 978cdce_handle_request(device_t dev, 979 const void *req, void **pptr, uint16_t *plen, 980 uint16_t offset, uint8_t *pstate) 981{ 982 return (ENXIO); /* use builtin handler */ 983} |
984 985#if CDCE_HAVE_NCM 986static uint8_t 987cdce_ncm_fill_tx_frames(struct usb_xfer *xfer, uint8_t index) 988{ 989 struct cdce_softc *sc = usbd_xfer_softc(xfer); 990 struct ifnet *ifp = uether_getifp(&sc->sc_ue); 991 struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, index); 992 struct mbuf *m; 993 uint32_t rem; 994 uint32_t offset; 995 uint32_t last_offset; 996 uint32_t n; 997 998 usbd_xfer_set_frame_offset(xfer, index * CDCE_NCM_TX_MAXLEN, index); 999 1000 offset = sizeof(sc->sc_ncm.hdr) + 1001 sizeof(sc->sc_ncm.dpt) + sizeof(sc->sc_ncm.dp); 1002 1003 /* Store last valid offset before alignment */ 1004 last_offset = offset; 1005 1006 /* Align offset correctly */ 1007 offset = sc->sc_ncm.tx_remainder - 1008 ((0UL - offset) & (0UL - sc->sc_ncm.tx_modulus)); 1009 1010 for (n = 0; n != CDCE_NCM_SUBFRAMES_MAX; n++) { 1011 1012 /* check if end of transmit buffer is reached */ 1013 1014 if (offset >= sc->sc_ncm.tx_max) 1015 break; 1016 1017 /* compute maximum buffer size */ 1018 1019 rem = sc->sc_ncm.tx_max - offset; 1020 1021 IFQ_DRV_DEQUEUE(&(ifp->if_snd), m); 1022 1023 if (m == NULL) 1024 break; 1025 1026 if (m->m_pkthdr.len > rem) { 1027 if (n == 0) { 1028 /* The frame won't fit in our buffer */ 1029 DPRINTFN(1, "Frame too big to be transmitted!\n"); 1030 m_freem(m); 1031 ifp->if_oerrors++; 1032 n--; 1033 continue; 1034 } 1035 /* Wait till next buffer becomes ready */ 1036 IFQ_DRV_PREPEND(&(ifp->if_snd), m); 1037 break; 1038 } 1039 usbd_m_copy_in(pc, offset, m, 0, m->m_pkthdr.len); 1040 1041 USETW(sc->sc_ncm.dp[n].wFrameLength, m->m_pkthdr.len); 1042 USETW(sc->sc_ncm.dp[n].wFrameIndex, offset); 1043 1044 /* Update offset */ 1045 offset += m->m_pkthdr.len; 1046 1047 /* Store last valid offset before alignment */ 1048 last_offset = offset; 1049 1050 /* Align offset correctly */ 1051 offset = sc->sc_ncm.tx_remainder - 1052 ((0UL - offset) & (0UL - sc->sc_ncm.tx_modulus)); 1053 1054 /* 1055 * If there's a BPF listener, bounce a copy 1056 * of this frame to him: 1057 */ 1058 BPF_MTAP(ifp, m); 1059 1060 /* Free mbuf */ 1061 1062 m_freem(m); 1063 1064 /* Pre-increment interface counter */ 1065 1066 ifp->if_opackets++; 1067 } 1068 1069 if (n == 0) 1070 return (1); 1071 1072 rem = (sizeof(sc->sc_ncm.dpt) + (4 * n) + 4); 1073 1074 USETW(sc->sc_ncm.dpt.wLength, rem); 1075 1076 /* zero the rest of the data pointer entries */ 1077 for (; n != CDCE_NCM_SUBFRAMES_MAX; n++) { 1078 USETW(sc->sc_ncm.dp[n].wFrameLength, 0); 1079 USETW(sc->sc_ncm.dp[n].wFrameIndex, 0); 1080 } 1081 1082 /* set frame length */ 1083 usbd_xfer_set_frame_len(xfer, index, last_offset); 1084 1085 /* Fill out 16-bit header */ 1086 sc->sc_ncm.hdr.dwSignature[0] = 'N'; 1087 sc->sc_ncm.hdr.dwSignature[1] = 'C'; 1088 sc->sc_ncm.hdr.dwSignature[2] = 'M'; 1089 sc->sc_ncm.hdr.dwSignature[3] = 'H'; 1090 USETW(sc->sc_ncm.hdr.wHeaderLength, sizeof(sc->sc_ncm.hdr)); 1091 USETW(sc->sc_ncm.hdr.wBlockLength, offset); 1092 USETW(sc->sc_ncm.hdr.wSequence, sc->sc_ncm.tx_seq); 1093 USETW(sc->sc_ncm.hdr.wDptIndex, sizeof(sc->sc_ncm.hdr)); 1094 1095 sc->sc_ncm.tx_seq++; 1096 1097 /* Fill out 16-bit frame table header */ 1098 sc->sc_ncm.dpt.dwSignature[0] = 'N'; 1099 sc->sc_ncm.dpt.dwSignature[1] = 'C'; 1100 sc->sc_ncm.dpt.dwSignature[2] = 'M'; 1101 sc->sc_ncm.dpt.dwSignature[3] = 'x'; 1102 USETW(sc->sc_ncm.dpt.wNextNdpIndex, 0); /* reserved */ 1103 1104 usbd_copy_in(pc, 0, &(sc->sc_ncm.hdr), sizeof(sc->sc_ncm.hdr)); 1105 usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr), &(sc->sc_ncm.dpt), 1106 sizeof(sc->sc_ncm.dpt)); 1107 usbd_copy_in(pc, sizeof(sc->sc_ncm.hdr) + sizeof(sc->sc_ncm.dpt), 1108 &(sc->sc_ncm.dp), sizeof(sc->sc_ncm.dp)); 1109 return (0); 1110} 1111 1112static void 1113cdce_ncm_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 1114{ 1115 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1116 struct ifnet *ifp = uether_getifp(&sc->sc_ue); 1117 uint16_t x; 1118 int actlen; 1119 int aframes; 1120 1121 switch (USB_GET_STATE(xfer)) { 1122 case USB_ST_TRANSFERRED: 1123 1124 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 1125 1126 DPRINTFN(10, "transfer complete: " 1127 "%u bytes in %u frames\n", actlen, aframes); 1128 1129 case USB_ST_SETUP: 1130 for (x = 0; x != CDCE_NCM_TX_FRAMES_MAX; x++) { 1131 if (cdce_ncm_fill_tx_frames(xfer, x)) 1132 break; 1133 } 1134 1135 if (x != 0) { 1136 usbd_xfer_set_frames(xfer, x); 1137 usbd_transfer_submit(xfer); 1138 } 1139 break; 1140 1141 default: /* Error */ 1142 DPRINTFN(10, "Transfer error: %s\n", 1143 usbd_errstr(error)); 1144 1145 /* update error counter */ 1146 ifp->if_oerrors += 1; 1147 1148 if (error != USB_ERR_CANCELLED) { 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 1158static void 1159cdce_ncm_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 1160{ 1161 struct cdce_softc *sc = usbd_xfer_softc(xfer); 1162 struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0); 1163 struct ifnet *ifp = uether_getifp(&sc->sc_ue); 1164 struct mbuf *m; 1165 int sumdata; 1166 int sumlen; 1167 int actlen; 1168 int aframes; 1169 int temp; 1170 int nframes; 1171 int x; 1172 int offset; 1173 1174 switch (USB_GET_STATE(xfer)) { 1175 case USB_ST_TRANSFERRED: 1176 1177 usbd_xfer_status(xfer, &actlen, &sumlen, &aframes, NULL); 1178 1179 DPRINTFN(1, "received %u bytes in %u frames\n", 1180 actlen, aframes); 1181 1182 if (actlen < (sizeof(sc->sc_ncm.hdr) + 1183 sizeof(sc->sc_ncm.dpt))) { 1184 DPRINTFN(1, "frame too short\n"); 1185 goto tr_stall; 1186 } 1187 usbd_copy_out(pc, 0, &(sc->sc_ncm.hdr), 1188 sizeof(sc->sc_ncm.hdr)); 1189 1190 if ((sc->sc_ncm.hdr.dwSignature[0] != 'N') || 1191 (sc->sc_ncm.hdr.dwSignature[1] != 'C') || 1192 (sc->sc_ncm.hdr.dwSignature[2] != 'M') || 1193 (sc->sc_ncm.hdr.dwSignature[3] != 'H')) { 1194 DPRINTFN(1, "invalid HDR signature\n"); 1195 goto tr_stall; 1196 } 1197 temp = UGETW(sc->sc_ncm.hdr.wBlockLength); 1198 if (temp > sumlen) { 1199 DPRINTFN(1, "unsupported block length %u/%u\n", 1200 temp, sumlen); 1201 goto tr_stall; 1202 } 1203 temp = UGETW(sc->sc_ncm.hdr.wDptIndex); 1204 if ((temp + sizeof(sc->sc_ncm.dpt)) > actlen) { 1205 DPRINTFN(1, "invalid DPT index\n"); 1206 goto tr_stall; 1207 } 1208 usbd_copy_out(pc, temp, &(sc->sc_ncm.dpt), 1209 sizeof(sc->sc_ncm.dpt)); 1210 1211 if ((sc->sc_ncm.dpt.dwSignature[0] != 'N') || 1212 (sc->sc_ncm.dpt.dwSignature[1] != 'C') || 1213 (sc->sc_ncm.dpt.dwSignature[2] != 'M') || 1214 (sc->sc_ncm.dpt.dwSignature[3] != 'x')) { 1215 DPRINTFN(1, "invalid DPT signature\n"); 1216 goto tr_stall; 1217 } 1218 nframes = UGETW(sc->sc_ncm.dpt.wLength) / 4; 1219 1220 /* Subtract size of header and last zero padded entry */ 1221 if (nframes >= (2 + 1)) 1222 nframes -= (2 + 1); 1223 else 1224 nframes = 0; 1225 1226 DPRINTFN(1, "nframes = %u\n", nframes); 1227 1228 temp += sizeof(sc->sc_ncm.dpt); 1229 1230 if ((temp + (4 * nframes)) > actlen) 1231 goto tr_stall; 1232 1233 if (nframes > CDCE_NCM_SUBFRAMES_MAX) { 1234 DPRINTFN(1, "Truncating number of frames from %u to %u\n", 1235 nframes, CDCE_NCM_SUBFRAMES_MAX); 1236 nframes = CDCE_NCM_SUBFRAMES_MAX; 1237 } 1238 usbd_copy_out(pc, temp, &(sc->sc_ncm.dp), (4 * nframes)); 1239 1240 sumdata = 0; 1241 1242 for (x = 0; x != nframes; x++) { 1243 1244 offset = UGETW(sc->sc_ncm.dp[x].wFrameIndex); 1245 temp = UGETW(sc->sc_ncm.dp[x].wFrameLength); 1246 if ((offset + temp) > actlen) { 1247 DPRINTFN(1, "invalid frame detected (ignored)\n"); 1248 m = NULL; 1249 1250 } else if (temp >= sizeof(struct ether_header)) { 1251 /* 1252 * allocate a suitable memory buffer, if 1253 * possible 1254 */ 1255 if (temp > (MCLBYTES - ETHER_ALIGN)) { 1256 m = NULL; 1257 continue; 1258 } if (temp > (MHLEN - ETHER_ALIGN)) { 1259 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1260 } else { 1261 m = m_gethdr(M_DONTWAIT, MT_DATA); 1262 } 1263 } else { 1264 m = NULL; /* dump it */ 1265 } 1266 1267 DPRINTFN(16, "frame %u, offset = %u, length = %u \n", 1268 x, offset, temp); 1269 1270 /* check if we have a buffer */ 1271 if (m) { 1272 m_adj(m, ETHER_ALIGN); 1273 1274 usbd_copy_out(pc, offset, m->m_data, temp); 1275 1276 /* enqueue */ 1277 uether_rxmbuf(&sc->sc_ue, m, temp); 1278 1279 sumdata += temp; 1280 } else { 1281 ifp->if_ierrors++; 1282 } 1283 } 1284 1285 DPRINTFN(1, "Efficiency: %u/%u bytes\n", sumdata, actlen); 1286 1287 case USB_ST_SETUP: 1288 usbd_xfer_set_frame_len(xfer, 0, sc->sc_ncm.rx_max); 1289 usbd_xfer_set_frames(xfer, 1); 1290 usbd_transfer_submit(xfer); 1291 uether_rxflush(&sc->sc_ue); /* must be last */ 1292 break; 1293 1294 default: /* Error */ 1295 DPRINTFN(1, "error = %s\n", 1296 usbd_errstr(error)); 1297 1298 if (error != USB_ERR_CANCELLED) { 1299tr_stall: 1300 /* try to clear stall first */ 1301 usbd_xfer_set_stall(xfer); 1302 usbd_xfer_set_frames(xfer, 0); 1303 usbd_transfer_submit(xfer); 1304 } 1305 break; 1306 } 1307} 1308#endif |
|