Merge branch 'vendor/MDOCML'
[dragonfly.git] / sys / bus / u4b / net / if_urndis.c
1 /*      $OpenBSD: if_urndis.c,v 1.46 2013/12/09 15:45:29 pirofti Exp $ */
2
3 /*
4  * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org>
5  * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org>
6  * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org>
7  * Copyright (c) 2014 Hans Petter Selasky <hselasky@freebsd.org>
8  * All rights reserved.
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * $FreeBSD: head/sys/dev/usb/net/if_urndis.c 261544 2014-02-06 10:47:47Z hselasky $
23  */
24
25 #include <sys/stdint.h>
26 #include <sys/param.h>
27 #include <sys/queue.h>
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/socket.h>
31 #include <sys/kernel.h>
32 #include <sys/bus.h>
33 #include <sys/module.h>
34 #include <sys/lock.h>
35 #include <sys/condvar.h>
36 #include <sys/sysctl.h>
37 #include <sys/unistd.h>
38 #include <sys/callout.h>
39 #include <sys/malloc.h>
40 #include <sys/priv.h>
41
42 #include <net/if.h>
43 #include <net/if_var.h>
44 #include <net/ifq_var.h>
45
46 #include <bus/u4b/usb.h>
47 #include <bus/u4b/usbdi.h>
48 #include <bus/u4b/usbdi_util.h>
49 #include "usbdevs.h"
50
51 #define USB_DEBUG_VAR urndis_debug
52 #include <bus/u4b/usb_debug.h>
53 #include <bus/u4b/usb_process.h>
54 #include "usb_if.h"
55
56 #include <bus/u4b/net/usb_ethernet.h>
57 #include <bus/u4b/net/if_urndisreg.h>
58
59 #include <bus/u4b/usb_cdc.h>
60
61 static device_probe_t urndis_probe;
62 static device_attach_t urndis_attach;
63 static device_detach_t urndis_detach;
64 static device_suspend_t urndis_suspend;
65 static device_resume_t urndis_resume;
66
67 static usb_callback_t urndis_bulk_write_callback;
68 static usb_callback_t urndis_bulk_read_callback;
69 static usb_callback_t urndis_intr_read_callback;
70
71 static uether_fn_t urndis_attach_post;
72 static uether_fn_t urndis_init;
73 static uether_fn_t urndis_stop;
74 static uether_fn_t urndis_start;
75 static uether_fn_t urndis_setmulti;
76 static uether_fn_t urndis_setpromisc;
77
78 static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, const void **, uint16_t *);
79 static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, struct urndis_set_req *, uint16_t);
80 static uint32_t urndis_ctrl_handle_init(struct urndis_softc *, const struct urndis_comp_hdr *);
81 static uint32_t urndis_ctrl_handle_query(struct urndis_softc *, const struct urndis_comp_hdr *, const void **, uint16_t *);
82 static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *, const struct urndis_comp_hdr *);
83 static uint32_t urndis_ctrl_init(struct urndis_softc *);
84
85 #ifdef USB_DEBUG
86 static int urndis_debug = 0;
87 static  SYSCTL_NODE(_hw_usb, OID_AUTO, urndis, CTLFLAG_RW, 0, "USB RNDIS-Ethernet");
88 SYSCTL_INT(_hw_usb_urndis, OID_AUTO, debug, CTLFLAG_RW, &urndis_debug, 0,
89     "Debug level");
90 #endif
91
92 static const struct usb_config urndis_config[URNDIS_N_TRANSFER] = {
93
94         [URNDIS_BULK_RX] = {
95                 .type = UE_BULK,
96                 .endpoint = UE_ADDR_ANY,
97                 .direction = UE_DIR_RX,
98                 .if_index = 0,
99                 .frames = 1,
100                 .bufsize = RNDIS_RX_MAXLEN,
101                 .flags = {.short_xfer_ok = 1,},
102                 .callback = urndis_bulk_read_callback,
103                 .timeout = 0,           /* no timeout */
104                 .usb_mode = USB_MODE_HOST,
105         },
106
107         [URNDIS_BULK_TX] = {
108                 .type = UE_BULK,
109                 .endpoint = UE_ADDR_ANY,
110                 .direction = UE_DIR_TX,
111                 .if_index = 0,
112                 .frames = RNDIS_TX_FRAMES_MAX,
113                 .bufsize = (RNDIS_TX_FRAMES_MAX * RNDIS_TX_MAXLEN),
114                 .flags = {
115                         .force_short_xfer = 1,
116                 },
117                 .callback = urndis_bulk_write_callback,
118                 .timeout = 10000,       /* 10 seconds */
119                 .usb_mode = USB_MODE_HOST,
120         },
121
122         [URNDIS_INTR_RX] = {
123                 .type = UE_INTERRUPT,
124                 .endpoint = UE_ADDR_ANY,
125                 .direction = UE_DIR_RX,
126                 .if_index = 1,
127                 .bufsize = 0,   /* use wMaxPacketSize */
128                 .flags = {.short_xfer_ok = 1,.no_pipe_ok = 1,},
129                 .callback = urndis_intr_read_callback,
130                 .timeout = 0,
131                 .usb_mode = USB_MODE_HOST,
132         },
133 };
134
135 static device_method_t urndis_methods[] = {
136         /* Device interface */
137         DEVMETHOD(device_probe, urndis_probe),
138         DEVMETHOD(device_attach, urndis_attach),
139         DEVMETHOD(device_detach, urndis_detach),
140         DEVMETHOD(device_suspend, urndis_suspend),
141         DEVMETHOD(device_resume, urndis_resume),
142
143         DEVMETHOD_END
144 };
145
146 static driver_t urndis_driver = {
147         .name = "urndis",
148         .methods = urndis_methods,
149         .size = sizeof(struct urndis_softc),
150 };
151
152 static devclass_t urndis_devclass;
153
154 DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, NULL);
155 MODULE_VERSION(urndis, 1);
156 MODULE_DEPEND(urndis, uether, 1, 1, 1);
157 MODULE_DEPEND(urndis, usb, 1, 1, 1);
158 MODULE_DEPEND(urndis, ether, 1, 1, 1);
159
160 static const struct usb_ether_methods urndis_ue_methods = {
161         .ue_attach_post = urndis_attach_post,
162         .ue_start = urndis_start,
163         .ue_init = urndis_init,
164         .ue_stop = urndis_stop,
165         .ue_setmulti = urndis_setmulti,
166         .ue_setpromisc = urndis_setpromisc,
167 };
168
169 static const STRUCT_USB_HOST_ID urndis_host_devs[] = {
170 #if 0
171         /* XXX this entry has a conflict an entry the umodem driver XXX */
172         {USB_IFACE_CLASS(UICLASS_CDC), USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
173         USB_IFACE_PROTOCOL(0xff)},
174 #endif
175         {USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF),
176         USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
177         {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC),
178         USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)},
179 };
180
181 static int
182 urndis_probe(device_t dev)
183 {
184         struct usb_attach_arg *uaa = device_get_ivars(dev);
185
186         return (usbd_lookup_id_by_uaa(urndis_host_devs, sizeof(urndis_host_devs), uaa));
187 }
188
189 static void
190 urndis_attach_post(struct usb_ether *ue)
191 {
192         /* no-op */
193         return;
194 }
195
196 static int
197 urndis_attach(device_t dev)
198 {
199         struct urndis_softc *sc = device_get_softc(dev);
200         struct usb_ether *ue = &sc->sc_ue;
201         struct usb_attach_arg *uaa = device_get_ivars(dev);
202         struct usb_cdc_cm_descriptor *cmd;
203         struct {
204                 struct urndis_set_req hdr;
205                 uint32_t filter;
206         } msg_filter;
207         const void *buf;
208         uint16_t bufsz;
209         uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex };
210         int error;
211         uint8_t i;
212
213         sc->sc_ue.ue_udev = uaa->device;
214         sc->sc_ifaceno_ctl = uaa->info.bIfaceNum;
215
216         cmd = usbd_find_descriptor(uaa->device, NULL, uaa->info.bIfaceIndex,
217             UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_CM, 0xFF);
218         if (cmd != NULL) {
219                 DPRINTF("Call Mode Descriptor found, dataif=%d\n", cmd->bDataInterface);
220                 iface_index[0] = cmd->bDataInterface;
221         }
222
223         device_set_usb_desc(dev);
224
225         lockinit(&sc->sc_lock, device_get_nameunit(dev), 0, LK_CANRECURSE);
226
227         /* scan the alternate settings looking for a valid one */
228
229         for (i = 0; i != 32; i++) {
230
231                 error = usbd_set_alt_interface_index(uaa->device,
232                     iface_index[0], i);
233
234                 if (error != 0)
235                         break;
236
237                 error = usbd_transfer_setup(uaa->device,
238                     iface_index, sc->sc_xfer, urndis_config,
239                     URNDIS_N_TRANSFER, sc, &sc->sc_lock);
240
241                 if (error == 0)
242                         break;
243         }
244
245         if ((error != 0) || (i == 32)) {
246                 device_printf(dev, "No valid alternate "
247                     "setting found\n");
248                 goto detach;
249         }
250         URNDIS_LOCK(sc);
251         error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, &buf, &bufsz);
252         URNDIS_UNLOCK(sc);
253
254         if (error != (int)RNDIS_STATUS_SUCCESS) {
255                 device_printf(dev, "Unable to get hardware address\n");
256                 goto detach;
257         }
258         if (bufsz != ETHER_ADDR_LEN) {
259                 device_printf(dev, "Invalid address length: %d bytes\n", bufsz);
260                 goto detach;
261         }
262         memcpy(&sc->sc_ue.ue_eaddr, buf, ETHER_ADDR_LEN);
263
264         /* Initialize packet filter */
265         sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST |
266             RNDIS_PACKET_TYPE_ALL_MULTICAST;
267         msg_filter.filter = htole32(sc->sc_filter);
268
269         URNDIS_LOCK(sc);
270         error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
271             &msg_filter.hdr, sizeof(msg_filter));
272         URNDIS_UNLOCK(sc);
273
274         if (error != (int)RNDIS_STATUS_SUCCESS) {
275                 device_printf(dev, "Unable to set data filters\n");
276                 goto detach;
277         }
278         ue->ue_sc = sc;
279         ue->ue_dev = dev;
280         ue->ue_udev = uaa->device;
281         ue->ue_lock = &sc->sc_lock;
282         ue->ue_methods = &urndis_ue_methods;
283
284         error = uether_ifattach(ue);
285         if (error) {
286                 device_printf(dev, "Could not attach interface\n");
287                 goto detach;
288         }
289
290         URNDIS_LOCK(sc);
291         /* start interrupt endpoint, if any */
292         usbd_transfer_start(sc->sc_xfer[URNDIS_INTR_RX]);
293         URNDIS_UNLOCK(sc);
294
295         return (0);                     /* success */
296
297 detach:
298         urndis_detach(dev);
299         return (ENXIO);                 /* failure */
300 }
301
302 static int
303 urndis_detach(device_t dev)
304 {
305         struct urndis_softc *sc = device_get_softc(dev);
306         struct usb_ether *ue = &sc->sc_ue;
307
308         /* stop all USB transfers first */
309         usbd_transfer_unsetup(sc->sc_xfer, URNDIS_N_TRANSFER);
310
311         uether_ifdetach(ue);
312
313         lockuninit(&sc->sc_lock);
314
315         return (0);
316 }
317
318 static void
319 urndis_start(struct usb_ether *ue)
320 {
321         struct urndis_softc *sc = uether_getsc(ue);
322
323         /*
324          * Start the USB transfers, if not already started:
325          */
326         usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_TX]);
327         usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_RX]);
328 }
329
330 static void
331 urndis_init(struct usb_ether *ue)
332 {
333         struct urndis_softc *sc = uether_getsc(ue);
334         struct ifnet *ifp = uether_getifp(ue);
335
336         URNDIS_LOCK_ASSERT(sc, MA_OWNED);
337
338         ifp->if_flags |= IFF_RUNNING;
339
340         urndis_ctrl_init(sc);
341
342         /* stall data write direction, which depends on USB mode */
343         usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]);
344
345         /* start data transfers */
346         urndis_start(ue);
347 }
348
349 static void
350 urndis_stop(struct usb_ether *ue)
351 {
352         struct urndis_softc *sc = uether_getsc(ue);
353         struct ifnet *ifp = uether_getifp(ue);
354
355         URNDIS_LOCK_ASSERT(sc, MA_OWNED);
356
357         ifp->if_flags &= ~IFF_RUNNING;
358
359         /*
360          * stop all the transfers, if not already stopped:
361          */
362         usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_RX]);
363         usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_TX]);
364 }
365
366 static void
367 urndis_setmulti(struct usb_ether *ue)
368 {
369         /* no-op */
370         return;
371 }
372
373 static void
374 urndis_setpromisc(struct usb_ether *ue)
375 {
376         /* no-op */
377         return;
378 }
379
380 static int
381 urndis_suspend(device_t dev)
382 {
383         device_printf(dev, "Suspending\n");
384         return (0);
385 }
386
387 static int
388 urndis_resume(device_t dev)
389 {
390         device_printf(dev, "Resuming\n");
391         return (0);
392 }
393
394 static usb_error_t
395 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
396     uint16_t index, uint16_t value, void *buf, uint16_t buflen)
397 {
398         usb_device_request_t req;
399
400         req.bmRequestType = rt;
401         req.bRequest = r;
402         USETW(req.wValue, value);
403         USETW(req.wIndex, index);
404         USETW(req.wLength, buflen);
405
406         return (usbd_do_request_flags(sc->sc_ue.ue_udev,
407             &sc->sc_lock, &req, buf, (rt & UT_READ) ?
408             USB_SHORT_XFER_OK : 0, NULL, 2000 /* ms */ ));
409 }
410
411 static usb_error_t
412 urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len)
413 {
414         usb_error_t err;
415
416         err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
417             sc->sc_ifaceno_ctl, 0, buf, len);
418
419         DPRINTF("%s\n", usbd_errstr(err));
420
421         return (err);
422 }
423
424 static struct urndis_comp_hdr *
425 urndis_ctrl_recv(struct urndis_softc *sc)
426 {
427         struct urndis_comp_hdr *hdr;
428         usb_error_t err;
429
430         err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
431             sc->sc_ifaceno_ctl, 0, sc->sc_response_buf, RNDIS_RESPONSE_LEN);
432
433         if (err != USB_ERR_NORMAL_COMPLETION)
434                 return (NULL);
435
436         hdr = (struct urndis_comp_hdr *)sc->sc_response_buf;
437
438         DPRINTF("type 0x%x len %u\n", le32toh(hdr->rm_type),
439             le32toh(hdr->rm_len));
440
441         if (le32toh(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
442                 DPRINTF("ctrl message error: wrong size %u > %u\n",
443                     le32toh(hdr->rm_len), RNDIS_RESPONSE_LEN);
444                 return (NULL);
445         }
446         return (hdr);
447 }
448
449 static uint32_t
450 urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
451     const void **buf, uint16_t *bufsz)
452 {
453         uint32_t rval;
454
455         DPRINTF("\n");
456
457         if (buf != NULL && bufsz != NULL) {
458                 *buf = NULL;
459                 *bufsz = 0;
460         }
461         switch (le32toh(hdr->rm_type)) {
462         case REMOTE_NDIS_INITIALIZE_CMPLT:
463                 rval = urndis_ctrl_handle_init(sc, hdr);
464                 break;
465
466         case REMOTE_NDIS_QUERY_CMPLT:
467                 rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
468                 break;
469
470         case REMOTE_NDIS_RESET_CMPLT:
471                 rval = urndis_ctrl_handle_reset(sc, hdr);
472                 break;
473
474         case REMOTE_NDIS_KEEPALIVE_CMPLT:
475         case REMOTE_NDIS_SET_CMPLT:
476                 rval = le32toh(hdr->rm_status);
477                 break;
478
479         default:
480                 DPRINTF("ctrl message error: unknown event 0x%x\n",
481                     le32toh(hdr->rm_type));
482                 rval = RNDIS_STATUS_FAILURE;
483                 break;
484         }
485         return (rval);
486 }
487
488 static uint32_t
489 urndis_ctrl_handle_init(struct urndis_softc *sc,
490     const struct urndis_comp_hdr *hdr)
491 {
492         const struct urndis_init_comp *msg;
493
494         msg = (const struct urndis_init_comp *)hdr;
495
496         DPRINTF("len %u rid %u status 0x%x "
497             "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
498             "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
499             le32toh(msg->rm_len),
500             le32toh(msg->rm_rid),
501             le32toh(msg->rm_status),
502             le32toh(msg->rm_ver_major),
503             le32toh(msg->rm_ver_minor),
504             le32toh(msg->rm_devflags),
505             le32toh(msg->rm_medium),
506             le32toh(msg->rm_pktmaxcnt),
507             le32toh(msg->rm_pktmaxsz),
508             le32toh(msg->rm_align),
509             le32toh(msg->rm_aflistoffset),
510             le32toh(msg->rm_aflistsz));
511
512         if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
513                 DPRINTF("init failed 0x%x\n", le32toh(msg->rm_status));
514                 return (le32toh(msg->rm_status));
515         }
516         if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
517                 DPRINTF("wrong device type (current type: 0x%x)\n",
518                     le32toh(msg->rm_devflags));
519                 return (RNDIS_STATUS_FAILURE);
520         }
521         if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
522                 DPRINTF("medium not 802.3 (current medium: 0x%x)\n",
523                     le32toh(msg->rm_medium));
524                 return (RNDIS_STATUS_FAILURE);
525         }
526         sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz);
527
528         return (le32toh(msg->rm_status));
529 }
530
531 static uint32_t
532 urndis_ctrl_handle_query(struct urndis_softc *sc,
533     const struct urndis_comp_hdr *hdr, const void **buf, uint16_t *bufsz)
534 {
535         const struct urndis_query_comp *msg;
536         uint64_t limit;
537
538         msg = (const struct urndis_query_comp *)hdr;
539
540         DPRINTF("len %u rid %u status 0x%x "
541             "buflen %u bufoff %u\n",
542             le32toh(msg->rm_len),
543             le32toh(msg->rm_rid),
544             le32toh(msg->rm_status),
545             le32toh(msg->rm_infobuflen),
546             le32toh(msg->rm_infobufoffset));
547
548         if (buf != NULL && bufsz != NULL) {
549                 *buf = NULL;
550                 *bufsz = 0;
551         }
552         if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
553                 DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status));
554                 return (le32toh(msg->rm_status));
555         }
556         limit = le32toh(msg->rm_infobuflen);
557         limit += le32toh(msg->rm_infobufoffset);
558         limit += RNDIS_HEADER_OFFSET;
559
560         if (limit > (uint64_t)le32toh(msg->rm_len)) {
561                 DPRINTF("ctrl message error: invalid query info "
562                     "len/offset/end_position(%u/%u/%u) -> "
563                     "go out of buffer limit %u\n",
564                     le32toh(msg->rm_infobuflen),
565                     le32toh(msg->rm_infobufoffset),
566                     le32toh(msg->rm_infobuflen) +
567                     le32toh(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
568                     le32toh(msg->rm_len));
569                 return (RNDIS_STATUS_FAILURE);
570         }
571         if (buf != NULL && bufsz != NULL) {
572                 *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET + le32toh(msg->rm_infobufoffset);
573                 *bufsz = le32toh(msg->rm_infobuflen);
574         }
575         return (le32toh(msg->rm_status));
576 }
577
578 static uint32_t
579 urndis_ctrl_handle_reset(struct urndis_softc *sc,
580     const struct urndis_comp_hdr *hdr)
581 {
582         const struct urndis_reset_comp *msg;
583         uint32_t rval;
584
585         msg = (const struct urndis_reset_comp *)hdr;
586
587         rval = le32toh(msg->rm_status);
588
589         DPRINTF("len %u status 0x%x "
590             "adrreset %u\n",
591             le32toh(msg->rm_len),
592             rval,
593             le32toh(msg->rm_adrreset));
594
595         if (rval != RNDIS_STATUS_SUCCESS) {
596                 DPRINTF("reset failed 0x%x\n", rval);
597                 return (rval);
598         }
599         if (msg->rm_adrreset != 0) {
600                 struct {
601                         struct urndis_set_req hdr;
602                         uint32_t filter;
603                 } msg_filter;
604
605                 msg_filter.filter = htole32(sc->sc_filter);
606
607                 rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
608                     &msg_filter.hdr, sizeof(msg_filter));
609
610                 if (rval != RNDIS_STATUS_SUCCESS) {
611                         DPRINTF("unable to reset data filters\n");
612                         return (rval);
613                 }
614         }
615         return (rval);
616 }
617
618 static uint32_t
619 urndis_ctrl_init(struct urndis_softc *sc)
620 {
621         struct urndis_init_req msg;
622         struct urndis_comp_hdr *hdr;
623         uint32_t rval;
624
625         msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
626         msg.rm_len = htole32(sizeof(msg));
627         msg.rm_rid = htole32(0);
628         msg.rm_ver_major = htole32(1);
629         msg.rm_ver_minor = htole32(1);
630         msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN);
631
632         DPRINTF("type %u len %u rid %u ver_major %u "
633             "ver_minor %u max_xfersz %u\n",
634             le32toh(msg.rm_type),
635             le32toh(msg.rm_len),
636             le32toh(msg.rm_rid),
637             le32toh(msg.rm_ver_major),
638             le32toh(msg.rm_ver_minor),
639             le32toh(msg.rm_max_xfersz));
640
641         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
642
643         if (rval != RNDIS_STATUS_SUCCESS) {
644                 DPRINTF("init failed\n");
645                 return (rval);
646         }
647         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
648                 DPRINTF("unable to get init response\n");
649                 return (RNDIS_STATUS_FAILURE);
650         }
651         rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
652
653         return (rval);
654 }
655
656 #if 0
657 static uint32_t
658 urndis_ctrl_halt(struct urndis_softc *sc)
659 {
660         struct urndis_halt_req msg;
661         uint32_t rval;
662
663         msg.rm_type = htole32(REMOTE_NDIS_HALT_MSG);
664         msg.rm_len = htole32(sizeof(msg));
665         msg.rm_rid = 0;
666
667         DPRINTF("type %u len %u rid %u\n",
668             le32toh(msg.rm_type),
669             le32toh(msg.rm_len),
670             le32toh(msg.rm_rid));
671
672         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
673
674         if (rval != RNDIS_STATUS_SUCCESS)
675                 printf("halt failed\n");
676
677         return (rval);
678 }
679
680 #endif
681
682 static uint32_t
683 urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, const void **rbuf, uint16_t *rbufsz)
684 {
685         struct urndis_query_req msg;
686         uint32_t rval;
687         struct urndis_comp_hdr *hdr;
688
689         msg.rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
690         msg.rm_len = htole32(sizeof(msg));
691         msg.rm_rid = 0;                 /* XXX */
692         msg.rm_oid = htole32(oid);
693         msg.rm_infobuflen = htole32(0);
694         msg.rm_infobufoffset = 0;
695         msg.rm_devicevchdl = 0;
696
697         DPRINTF("type %u len %u rid %u oid 0x%x "
698             "infobuflen %u infobufoffset %u devicevchdl %u\n",
699             le32toh(msg.rm_type),
700             le32toh(msg.rm_len),
701             le32toh(msg.rm_rid),
702             le32toh(msg.rm_oid),
703             le32toh(msg.rm_infobuflen),
704             le32toh(msg.rm_infobufoffset),
705             le32toh(msg.rm_devicevchdl));
706
707         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
708
709         if (rval != RNDIS_STATUS_SUCCESS) {
710                 DPRINTF("query failed\n");
711                 return (rval);
712         }
713         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
714                 DPRINTF("unable to get query response\n");
715                 return (RNDIS_STATUS_FAILURE);
716         }
717         rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
718
719         return (rval);
720 }
721
722 static uint32_t
723 urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, struct urndis_set_req *msg, uint16_t len)
724 {
725         struct urndis_comp_hdr *hdr;
726         uint32_t rval;
727         uint32_t datalen = len - sizeof(*msg);
728
729         msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
730         msg->rm_len = htole32(len);
731         msg->rm_rid = 0;                /* XXX */
732         msg->rm_oid = htole32(oid);
733         msg->rm_infobuflen = htole32(datalen);
734         if (datalen != 0) {
735                 msg->rm_infobufoffset = htole32(sizeof(*msg) - RNDIS_HEADER_OFFSET);
736         } else {
737                 msg->rm_infobufoffset = 0;
738         }
739         msg->rm_devicevchdl = 0;
740
741         DPRINTF("type %u len %u rid %u oid 0x%x "
742             "infobuflen %u infobufoffset %u devicevchdl %u\n",
743             le32toh(msg->rm_type),
744             le32toh(msg->rm_len),
745             le32toh(msg->rm_rid),
746             le32toh(msg->rm_oid),
747             le32toh(msg->rm_infobuflen),
748             le32toh(msg->rm_infobufoffset),
749             le32toh(msg->rm_devicevchdl));
750
751         rval = urndis_ctrl_send(sc, msg, len);
752
753         if (rval != RNDIS_STATUS_SUCCESS) {
754                 DPRINTF("set failed\n");
755                 return (rval);
756         }
757         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
758                 DPRINTF("unable to get set response\n");
759                 return (RNDIS_STATUS_FAILURE);
760         }
761         rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
762         if (rval != RNDIS_STATUS_SUCCESS)
763                 DPRINTF("set failed 0x%x\n", rval);
764
765         return (rval);
766 }
767
768 static void
769 urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
770 {
771         struct urndis_softc *sc = usbd_xfer_softc(xfer);
772         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
773         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
774         struct urndis_packet_msg msg;
775         struct mbuf *m;
776         int actlen;
777         int aframes;
778         int offset;
779
780         switch (USB_GET_STATE(xfer)) {
781         case USB_ST_TRANSFERRED:
782
783                 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
784
785                 DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes);
786
787                 for (offset = 0; actlen >= (uint32_t)sizeof(msg);) {
788
789                         /* copy out header */
790                         usbd_copy_out(pc, offset, &msg, sizeof(msg));
791
792                         if (le32toh(0x1234567U) != 0x1234567U) {
793                                 /* swap endianness */
794                                 msg.rm_type = le32toh(msg.rm_type);
795                                 msg.rm_len = le32toh(msg.rm_len);
796                                 msg.rm_dataoffset = le32toh(msg.rm_dataoffset);
797                                 msg.rm_datalen = le32toh(msg.rm_datalen);
798                                 msg.rm_oobdataoffset = le32toh(msg.rm_oobdataoffset);
799                                 msg.rm_oobdatalen = le32toh(msg.rm_oobdatalen);
800                                 msg.rm_oobdataelements = le32toh(msg.rm_oobdataelements);
801                                 msg.rm_pktinfooffset = le32toh(msg.rm_pktinfooffset);
802                                 msg.rm_pktinfolen = le32toh(msg.rm_pktinfolen);
803                                 msg.rm_vchandle = le32toh(msg.rm_vchandle);
804                                 msg.rm_reserved = le32toh(msg.rm_reserved);
805                         }
806
807                         DPRINTF("len %u data(off:%u len:%u) "
808                             "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
809                             msg.rm_len, msg.rm_dataoffset, msg.rm_datalen,
810                             msg.rm_oobdataoffset, msg.rm_oobdatalen,
811                             msg.rm_oobdataelements, msg.rm_pktinfooffset,
812                             msg.rm_pktinfooffset);
813
814                         /* sanity check the RNDIS header */
815                         if (msg.rm_type != REMOTE_NDIS_PACKET_MSG) {
816                                 DPRINTF("invalid type 0x%x != 0x%x\n",
817                                     msg.rm_type, REMOTE_NDIS_PACKET_MSG);
818                                 goto tr_setup;
819                         } else if (msg.rm_len < (uint32_t)sizeof(msg)) {
820                                 DPRINTF("invalid msg len %u < %u\n",
821                                     msg.rm_len, (unsigned)sizeof(msg));
822                                 goto tr_setup;
823                         } else if (msg.rm_len > (uint32_t)actlen) {
824                                 DPRINTF("invalid msg len %u > buffer "
825                                     "len %u\n", msg.rm_len, actlen);
826                                 goto tr_setup;
827                         } else if (msg.rm_dataoffset >= (uint32_t)actlen) {
828                                 DPRINTF("invalid msg dataoffset %u > buffer "
829                                     "dataoffset %u\n", msg.rm_dataoffset, actlen);
830                                 goto tr_setup;
831                         } else if (msg.rm_datalen > (uint32_t)actlen) {
832                                 DPRINTF("invalid msg datalen %u > buffer "
833                                     "datalen %u\n", msg.rm_datalen, actlen);
834                                 goto tr_setup;
835                         } else if ((msg.rm_dataoffset + msg.rm_datalen +
836                             (uint32_t)__offsetof(struct urndis_packet_msg,
837                             rm_dataoffset)) > (uint32_t)actlen) {
838                                 DPRINTF("invalid dataoffset %u larger than %u\n",
839                                     msg.rm_dataoffset + msg.rm_datalen +
840                                     (uint32_t)__offsetof(struct urndis_packet_msg,
841                                     rm_dataoffset), actlen);
842                                 goto tr_setup;
843                         } else if (msg.rm_datalen < (uint32_t)sizeof(struct ether_header)) {
844                                 ifp->if_ierrors++;
845                                 DPRINTF("invalid ethernet size "
846                                     "%u < %u\n", msg.rm_datalen, (unsigned)sizeof(struct ether_header));
847                                 goto tr_setup;
848                         } else if (msg.rm_datalen > (uint32_t)MCLBYTES) {
849                                 ifp->if_ierrors++;
850                                 DPRINTF("invalid ethernet size "
851                                     "%u > %u\n",
852                                     msg.rm_datalen, (unsigned)MCLBYTES);
853                                 goto tr_setup;
854                         } else if (msg.rm_datalen > (uint32_t)(MHLEN - ETHER_ALIGN)) {
855                                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
856                         } else {
857                                 m = m_gethdr(M_NOWAIT, MT_DATA);
858                         }
859
860                         /* check if we have a buffer */
861                         if (m != NULL) {
862                                 m_adj(m, ETHER_ALIGN);
863
864                                 usbd_copy_out(pc, offset + msg.rm_dataoffset +
865                                     __offsetof(struct urndis_packet_msg,
866                                     rm_dataoffset), m->m_data, msg.rm_datalen);
867
868                                 /* enqueue */
869                                 uether_rxmbuf(&sc->sc_ue, m, msg.rm_datalen);
870                         } else {
871                                 ifp->if_ierrors++;
872                         }
873                         offset += msg.rm_len;
874                         actlen -= msg.rm_len;
875                 }
876
877         case USB_ST_SETUP:
878 tr_setup:
879                 usbd_xfer_set_frame_len(xfer, 0, RNDIS_RX_MAXLEN);
880                 usbd_xfer_set_frames(xfer, 1);
881                 usbd_transfer_submit(xfer);
882                 uether_rxflush(&sc->sc_ue);     /* must be last */
883                 break;
884
885         default:                        /* Error */
886                 DPRINTFN(1, "error = %s\n", usbd_errstr(error));
887
888                 if (error != USB_ERR_CANCELLED) {
889                         /* try to clear stall first */
890                         usbd_xfer_set_stall(xfer);
891                         usbd_xfer_set_frames(xfer, 0);
892                         usbd_transfer_submit(xfer);
893                 }
894                 break;
895         }
896 }
897
898 static void
899 urndis_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
900 {
901         struct urndis_packet_msg msg;
902         struct urndis_softc *sc = usbd_xfer_softc(xfer);
903         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
904         struct mbuf *m;
905         unsigned x;
906         int actlen;
907         int aframes;
908
909         usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
910
911         DPRINTFN(1, "\n");
912
913         switch (USB_GET_STATE(xfer)) {
914         case USB_ST_TRANSFERRED:
915                 DPRINTFN(11, "%u bytes in %u frames\n", actlen, aframes);
916
917                 ifp->if_opackets++;
918
919                 /* FALLTHROUGH */
920         case USB_ST_SETUP:
921 tr_setup:
922                 memset(&msg, 0, sizeof(msg));
923
924                 for (x = 0; x != RNDIS_TX_FRAMES_MAX; x++) {
925                         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, x);
926
927                         usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x);
928
929         next_pkt:
930                         m = ifq_dequeue(&ifp->if_snd);
931
932                         if (m == NULL)
933                                 break;
934
935                         if ((m->m_pkthdr.len + sizeof(msg)) > RNDIS_TX_MAXLEN) {
936                                 DPRINTF("Too big packet\n");
937                                 ifp->if_oerrors++;
938
939                                 /* Free buffer */
940                                 m_freem(m);
941                                 goto next_pkt;
942                         }
943                         msg.rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
944                         msg.rm_len = htole32(sizeof(msg) + m->m_pkthdr.len);
945
946                         msg.rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
947                         msg.rm_datalen = htole32(m->m_pkthdr.len);
948
949                         /* copy in all data */
950                         usbd_copy_in(pc, 0, &msg, sizeof(msg));
951                         usbd_m_copy_in(pc, sizeof(msg), m, 0, m->m_pkthdr.len);
952                         usbd_xfer_set_frame_len(xfer, x, sizeof(msg) + m->m_pkthdr.len);
953
954                         /*
955                          * If there's a BPF listener, bounce a copy of
956                          * this frame to him:
957                          */
958                         BPF_MTAP(ifp, m);
959
960                         /* Free buffer */
961                         m_freem(m);
962                 }
963                 if (x != 0) {
964                         usbd_xfer_set_frames(xfer, x);
965                         usbd_transfer_submit(xfer);
966                 }
967                 break;
968
969         default:                        /* Error */
970                 DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error));
971
972                 /* count output errors */
973                 ifp->if_oerrors++;
974
975                 if (error != USB_ERR_CANCELLED) {
976                         /* try to clear stall first */
977                         usbd_xfer_set_stall(xfer);
978                         goto tr_setup;
979                 }
980                 break;
981         }
982 }
983
984 static void
985 urndis_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
986 {
987         int actlen;
988
989         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
990
991         switch (USB_GET_STATE(xfer)) {
992         case USB_ST_TRANSFERRED:
993
994                 DPRINTF("Received %d bytes\n", actlen);
995
996                 /* TODO: decode some indications */
997
998                 /* FALLTHROUGH */
999         case USB_ST_SETUP:
1000 tr_setup:
1001                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1002                 usbd_transfer_submit(xfer);
1003                 break;
1004
1005         default:                        /* Error */
1006                 if (error != USB_ERR_CANCELLED) {
1007                         /* start clear stall */
1008                         usbd_xfer_set_stall(xfer);
1009                         goto tr_setup;
1010                 }
1011                 break;
1012         }
1013 }