Deleted Added
full compact
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