Merge branch 'vendor/GCC50'
[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         /* Generic RNDIS class match */
171         {USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF),
172         USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
173         {USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC),
174         USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)},
175         /* HP-WebOS */
176         {USB_VENDOR(USB_VENDOR_PALM), USB_IFACE_CLASS(UICLASS_CDC),
177                 USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
178                 USB_IFACE_PROTOCOL(0xff)},
179 };
180
181 static const STRUCT_USB_HOST_ID urndis_non_huawei_host_devs[] = {
182         {USB_IFACE_CLASS(UICLASS_CDC),
183         USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
184         USB_IFACE_PROTOCOL(0xff)},
185 };
186
187 static int
188 urndis_probe(device_t dev)
189 {
190         int res;
191         struct usb_attach_arg *uaa = device_get_ivars(dev);
192
193         res = usbd_lookup_id_by_uaa(urndis_host_devs,
194             sizeof(urndis_host_devs), uaa);
195         if (res == 0)
196                 return(0);
197         if (uaa->info.idVendor == USB_VENDOR_HUAWEI)
198                 return(ENXIO);
199         return (usbd_lookup_id_by_uaa(urndis_non_huawei_host_devs,
200                 sizeof(urndis_non_huawei_host_devs), uaa));
201 }
202
203 static void
204 urndis_attach_post(struct usb_ether *ue)
205 {
206         /* no-op */
207         return;
208 }
209
210 static int
211 urndis_attach(device_t dev)
212 {
213         struct urndis_softc *sc = device_get_softc(dev);
214         struct usb_ether *ue = &sc->sc_ue;
215         struct usb_attach_arg *uaa = device_get_ivars(dev);
216         struct usb_cdc_cm_descriptor *cmd;
217         struct {
218                 struct urndis_set_req hdr;
219                 uint32_t filter;
220         } msg_filter;
221         const void *buf;
222         uint16_t bufsz;
223         uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex };
224         int error;
225         uint8_t i;
226
227         sc->sc_ue.ue_udev = uaa->device;
228         sc->sc_ifaceno_ctl = uaa->info.bIfaceNum;
229
230         cmd = usbd_find_descriptor(uaa->device, NULL, uaa->info.bIfaceIndex,
231             UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_CM, 0xFF);
232         if (cmd != NULL) {
233                 DPRINTF("Call Mode Descriptor found, dataif=%d\n", cmd->bDataInterface);
234                 iface_index[0] = cmd->bDataInterface;
235         }
236
237         device_set_usb_desc(dev);
238
239         lockinit(&sc->sc_lock, device_get_nameunit(dev), 0, LK_CANRECURSE);
240
241         /* scan the alternate settings looking for a valid one */
242
243         for (i = 0; i != 32; i++) {
244
245                 error = usbd_set_alt_interface_index(uaa->device,
246                     iface_index[0], i);
247
248                 if (error != 0)
249                         break;
250
251                 error = usbd_transfer_setup(uaa->device,
252                     iface_index, sc->sc_xfer, urndis_config,
253                     URNDIS_N_TRANSFER, sc, &sc->sc_lock);
254
255                 if (error == 0)
256                         break;
257         }
258
259         if ((error != 0) || (i == 32)) {
260                 device_printf(dev, "No valid alternate "
261                     "setting found\n");
262                 goto detach;
263         }
264         URNDIS_LOCK(sc);
265         error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, &buf, &bufsz);
266         URNDIS_UNLOCK(sc);
267
268         if (error != (int)RNDIS_STATUS_SUCCESS) {
269                 device_printf(dev, "Unable to get hardware address\n");
270                 goto detach;
271         }
272         if (bufsz != ETHER_ADDR_LEN) {
273                 device_printf(dev, "Invalid address length: %d bytes\n", bufsz);
274                 goto detach;
275         }
276         memcpy(&sc->sc_ue.ue_eaddr, buf, ETHER_ADDR_LEN);
277
278         /* Initialize packet filter */
279         sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST |
280             RNDIS_PACKET_TYPE_ALL_MULTICAST;
281         msg_filter.filter = htole32(sc->sc_filter);
282
283         URNDIS_LOCK(sc);
284         error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
285             &msg_filter.hdr, sizeof(msg_filter));
286         URNDIS_UNLOCK(sc);
287
288         if (error != (int)RNDIS_STATUS_SUCCESS) {
289                 device_printf(dev, "Unable to set data filters\n");
290                 goto detach;
291         }
292         ue->ue_sc = sc;
293         ue->ue_dev = dev;
294         ue->ue_udev = uaa->device;
295         ue->ue_lock = &sc->sc_lock;
296         ue->ue_methods = &urndis_ue_methods;
297
298         error = uether_ifattach(ue);
299         if (error) {
300                 device_printf(dev, "Could not attach interface\n");
301                 goto detach;
302         }
303
304         URNDIS_LOCK(sc);
305         /* start interrupt endpoint, if any */
306         usbd_transfer_start(sc->sc_xfer[URNDIS_INTR_RX]);
307         URNDIS_UNLOCK(sc);
308
309         return (0);                     /* success */
310
311 detach:
312         urndis_detach(dev);
313         return (ENXIO);                 /* failure */
314 }
315
316 static int
317 urndis_detach(device_t dev)
318 {
319         struct urndis_softc *sc = device_get_softc(dev);
320         struct usb_ether *ue = &sc->sc_ue;
321
322         /* stop all USB transfers first */
323         usbd_transfer_unsetup(sc->sc_xfer, URNDIS_N_TRANSFER);
324
325         uether_ifdetach(ue);
326
327         lockuninit(&sc->sc_lock);
328
329         return (0);
330 }
331
332 static void
333 urndis_start(struct usb_ether *ue)
334 {
335         struct urndis_softc *sc = uether_getsc(ue);
336
337         /*
338          * Start the USB transfers, if not already started:
339          */
340         usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_TX]);
341         usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_RX]);
342 }
343
344 static void
345 urndis_init(struct usb_ether *ue)
346 {
347         struct urndis_softc *sc = uether_getsc(ue);
348         struct ifnet *ifp = uether_getifp(ue);
349
350         URNDIS_LOCK_ASSERT(sc);
351
352         ifp->if_flags |= IFF_RUNNING;
353
354         urndis_ctrl_init(sc);
355
356         /* stall data write direction, which depends on USB mode */
357         usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]);
358
359         /* start data transfers */
360         urndis_start(ue);
361 }
362
363 static void
364 urndis_stop(struct usb_ether *ue)
365 {
366         struct urndis_softc *sc = uether_getsc(ue);
367         struct ifnet *ifp = uether_getifp(ue);
368
369         URNDIS_LOCK_ASSERT(sc);
370
371         ifp->if_flags &= ~IFF_RUNNING;
372
373         /*
374          * stop all the transfers, if not already stopped:
375          */
376         usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_RX]);
377         usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_TX]);
378 }
379
380 static void
381 urndis_setmulti(struct usb_ether *ue)
382 {
383         /* no-op */
384         return;
385 }
386
387 static void
388 urndis_setpromisc(struct usb_ether *ue)
389 {
390         /* no-op */
391         return;
392 }
393
394 static int
395 urndis_suspend(device_t dev)
396 {
397         device_printf(dev, "Suspending\n");
398         return (0);
399 }
400
401 static int
402 urndis_resume(device_t dev)
403 {
404         device_printf(dev, "Resuming\n");
405         return (0);
406 }
407
408 static usb_error_t
409 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
410     uint16_t index, uint16_t value, void *buf, uint16_t buflen)
411 {
412         usb_device_request_t req;
413
414         req.bmRequestType = rt;
415         req.bRequest = r;
416         USETW(req.wValue, value);
417         USETW(req.wIndex, index);
418         USETW(req.wLength, buflen);
419
420         return (usbd_do_request_flags(sc->sc_ue.ue_udev,
421             &sc->sc_lock, &req, buf, (rt & UT_READ) ?
422             USB_SHORT_XFER_OK : 0, NULL, 2000 /* ms */ ));
423 }
424
425 static usb_error_t
426 urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len)
427 {
428         usb_error_t err;
429
430         err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
431             sc->sc_ifaceno_ctl, 0, buf, len);
432
433         DPRINTF("%s\n", usbd_errstr(err));
434
435         return (err);
436 }
437
438 static struct urndis_comp_hdr *
439 urndis_ctrl_recv(struct urndis_softc *sc)
440 {
441         struct urndis_comp_hdr *hdr;
442         usb_error_t err;
443
444         err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
445             sc->sc_ifaceno_ctl, 0, sc->sc_response_buf, RNDIS_RESPONSE_LEN);
446
447         if (err != USB_ERR_NORMAL_COMPLETION)
448                 return (NULL);
449
450         hdr = (struct urndis_comp_hdr *)sc->sc_response_buf;
451
452         DPRINTF("type 0x%x len %u\n", le32toh(hdr->rm_type),
453             le32toh(hdr->rm_len));
454
455         if (le32toh(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
456                 DPRINTF("ctrl message error: wrong size %u > %u\n",
457                     le32toh(hdr->rm_len), RNDIS_RESPONSE_LEN);
458                 return (NULL);
459         }
460         return (hdr);
461 }
462
463 static uint32_t
464 urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
465     const void **buf, uint16_t *bufsz)
466 {
467         uint32_t rval;
468
469         DPRINTF("\n");
470
471         if (buf != NULL && bufsz != NULL) {
472                 *buf = NULL;
473                 *bufsz = 0;
474         }
475         switch (le32toh(hdr->rm_type)) {
476         case REMOTE_NDIS_INITIALIZE_CMPLT:
477                 rval = urndis_ctrl_handle_init(sc, hdr);
478                 break;
479
480         case REMOTE_NDIS_QUERY_CMPLT:
481                 rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
482                 break;
483
484         case REMOTE_NDIS_RESET_CMPLT:
485                 rval = urndis_ctrl_handle_reset(sc, hdr);
486                 break;
487
488         case REMOTE_NDIS_KEEPALIVE_CMPLT:
489         case REMOTE_NDIS_SET_CMPLT:
490                 rval = le32toh(hdr->rm_status);
491                 break;
492
493         default:
494                 DPRINTF("ctrl message error: unknown event 0x%x\n",
495                     le32toh(hdr->rm_type));
496                 rval = RNDIS_STATUS_FAILURE;
497                 break;
498         }
499         return (rval);
500 }
501
502 static uint32_t
503 urndis_ctrl_handle_init(struct urndis_softc *sc,
504     const struct urndis_comp_hdr *hdr)
505 {
506         const struct urndis_init_comp *msg;
507
508         msg = (const struct urndis_init_comp *)hdr;
509
510         DPRINTF("len %u rid %u status 0x%x "
511             "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
512             "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
513             le32toh(msg->rm_len),
514             le32toh(msg->rm_rid),
515             le32toh(msg->rm_status),
516             le32toh(msg->rm_ver_major),
517             le32toh(msg->rm_ver_minor),
518             le32toh(msg->rm_devflags),
519             le32toh(msg->rm_medium),
520             le32toh(msg->rm_pktmaxcnt),
521             le32toh(msg->rm_pktmaxsz),
522             le32toh(msg->rm_align),
523             le32toh(msg->rm_aflistoffset),
524             le32toh(msg->rm_aflistsz));
525
526         if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
527                 DPRINTF("init failed 0x%x\n", le32toh(msg->rm_status));
528                 return (le32toh(msg->rm_status));
529         }
530         if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
531                 DPRINTF("wrong device type (current type: 0x%x)\n",
532                     le32toh(msg->rm_devflags));
533                 return (RNDIS_STATUS_FAILURE);
534         }
535         if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
536                 DPRINTF("medium not 802.3 (current medium: 0x%x)\n",
537                     le32toh(msg->rm_medium));
538                 return (RNDIS_STATUS_FAILURE);
539         }
540         sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz);
541
542         return (le32toh(msg->rm_status));
543 }
544
545 static uint32_t
546 urndis_ctrl_handle_query(struct urndis_softc *sc,
547     const struct urndis_comp_hdr *hdr, const void **buf, uint16_t *bufsz)
548 {
549         const struct urndis_query_comp *msg;
550         uint64_t limit;
551
552         msg = (const struct urndis_query_comp *)hdr;
553
554         DPRINTF("len %u rid %u status 0x%x "
555             "buflen %u bufoff %u\n",
556             le32toh(msg->rm_len),
557             le32toh(msg->rm_rid),
558             le32toh(msg->rm_status),
559             le32toh(msg->rm_infobuflen),
560             le32toh(msg->rm_infobufoffset));
561
562         if (buf != NULL && bufsz != NULL) {
563                 *buf = NULL;
564                 *bufsz = 0;
565         }
566         if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
567                 DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status));
568                 return (le32toh(msg->rm_status));
569         }
570         limit = le32toh(msg->rm_infobuflen);
571         limit += le32toh(msg->rm_infobufoffset);
572         limit += RNDIS_HEADER_OFFSET;
573
574         if (limit > (uint64_t)le32toh(msg->rm_len)) {
575                 DPRINTF("ctrl message error: invalid query info "
576                     "len/offset/end_position(%u/%u/%u) -> "
577                     "go out of buffer limit %u\n",
578                     le32toh(msg->rm_infobuflen),
579                     le32toh(msg->rm_infobufoffset),
580                     le32toh(msg->rm_infobuflen) +
581                     le32toh(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
582                     le32toh(msg->rm_len));
583                 return (RNDIS_STATUS_FAILURE);
584         }
585         if (buf != NULL && bufsz != NULL) {
586                 *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET + le32toh(msg->rm_infobufoffset);
587                 *bufsz = le32toh(msg->rm_infobuflen);
588         }
589         return (le32toh(msg->rm_status));
590 }
591
592 static uint32_t
593 urndis_ctrl_handle_reset(struct urndis_softc *sc,
594     const struct urndis_comp_hdr *hdr)
595 {
596         const struct urndis_reset_comp *msg;
597         uint32_t rval;
598
599         msg = (const struct urndis_reset_comp *)hdr;
600
601         rval = le32toh(msg->rm_status);
602
603         DPRINTF("len %u status 0x%x "
604             "adrreset %u\n",
605             le32toh(msg->rm_len),
606             rval,
607             le32toh(msg->rm_adrreset));
608
609         if (rval != RNDIS_STATUS_SUCCESS) {
610                 DPRINTF("reset failed 0x%x\n", rval);
611                 return (rval);
612         }
613         if (msg->rm_adrreset != 0) {
614                 struct {
615                         struct urndis_set_req hdr;
616                         uint32_t filter;
617                 } msg_filter;
618
619                 msg_filter.filter = htole32(sc->sc_filter);
620
621                 rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
622                     &msg_filter.hdr, sizeof(msg_filter));
623
624                 if (rval != RNDIS_STATUS_SUCCESS) {
625                         DPRINTF("unable to reset data filters\n");
626                         return (rval);
627                 }
628         }
629         return (rval);
630 }
631
632 static uint32_t
633 urndis_ctrl_init(struct urndis_softc *sc)
634 {
635         struct urndis_init_req msg;
636         struct urndis_comp_hdr *hdr;
637         uint32_t rval;
638
639         msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
640         msg.rm_len = htole32(sizeof(msg));
641         msg.rm_rid = htole32(0);
642         msg.rm_ver_major = htole32(1);
643         msg.rm_ver_minor = htole32(1);
644         msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN);
645
646         DPRINTF("type %u len %u rid %u ver_major %u "
647             "ver_minor %u max_xfersz %u\n",
648             le32toh(msg.rm_type),
649             le32toh(msg.rm_len),
650             le32toh(msg.rm_rid),
651             le32toh(msg.rm_ver_major),
652             le32toh(msg.rm_ver_minor),
653             le32toh(msg.rm_max_xfersz));
654
655         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
656
657         if (rval != RNDIS_STATUS_SUCCESS) {
658                 DPRINTF("init failed\n");
659                 return (rval);
660         }
661         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
662                 DPRINTF("unable to get init response\n");
663                 return (RNDIS_STATUS_FAILURE);
664         }
665         rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
666
667         return (rval);
668 }
669
670 #if 0
671 static uint32_t
672 urndis_ctrl_halt(struct urndis_softc *sc)
673 {
674         struct urndis_halt_req msg;
675         uint32_t rval;
676
677         msg.rm_type = htole32(REMOTE_NDIS_HALT_MSG);
678         msg.rm_len = htole32(sizeof(msg));
679         msg.rm_rid = 0;
680
681         DPRINTF("type %u len %u rid %u\n",
682             le32toh(msg.rm_type),
683             le32toh(msg.rm_len),
684             le32toh(msg.rm_rid));
685
686         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
687
688         if (rval != RNDIS_STATUS_SUCCESS)
689                 printf("halt failed\n");
690
691         return (rval);
692 }
693
694 #endif
695
696 static uint32_t
697 urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, const void **rbuf, uint16_t *rbufsz)
698 {
699         struct urndis_query_req msg;
700         uint32_t rval;
701         struct urndis_comp_hdr *hdr;
702
703         msg.rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
704         msg.rm_len = htole32(sizeof(msg));
705         msg.rm_rid = 0;                 /* XXX */
706         msg.rm_oid = htole32(oid);
707         msg.rm_infobuflen = htole32(0);
708         msg.rm_infobufoffset = 0;
709         msg.rm_devicevchdl = 0;
710
711         DPRINTF("type %u len %u rid %u oid 0x%x "
712             "infobuflen %u infobufoffset %u devicevchdl %u\n",
713             le32toh(msg.rm_type),
714             le32toh(msg.rm_len),
715             le32toh(msg.rm_rid),
716             le32toh(msg.rm_oid),
717             le32toh(msg.rm_infobuflen),
718             le32toh(msg.rm_infobufoffset),
719             le32toh(msg.rm_devicevchdl));
720
721         rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
722
723         if (rval != RNDIS_STATUS_SUCCESS) {
724                 DPRINTF("query failed\n");
725                 return (rval);
726         }
727         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
728                 DPRINTF("unable to get query response\n");
729                 return (RNDIS_STATUS_FAILURE);
730         }
731         rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
732
733         return (rval);
734 }
735
736 static uint32_t
737 urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, struct urndis_set_req *msg, uint16_t len)
738 {
739         struct urndis_comp_hdr *hdr;
740         uint32_t rval;
741         uint32_t datalen = len - sizeof(*msg);
742
743         msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
744         msg->rm_len = htole32(len);
745         msg->rm_rid = 0;                /* XXX */
746         msg->rm_oid = htole32(oid);
747         msg->rm_infobuflen = htole32(datalen);
748         if (datalen != 0) {
749                 msg->rm_infobufoffset = htole32(sizeof(*msg) - RNDIS_HEADER_OFFSET);
750         } else {
751                 msg->rm_infobufoffset = 0;
752         }
753         msg->rm_devicevchdl = 0;
754
755         DPRINTF("type %u len %u rid %u oid 0x%x "
756             "infobuflen %u infobufoffset %u devicevchdl %u\n",
757             le32toh(msg->rm_type),
758             le32toh(msg->rm_len),
759             le32toh(msg->rm_rid),
760             le32toh(msg->rm_oid),
761             le32toh(msg->rm_infobuflen),
762             le32toh(msg->rm_infobufoffset),
763             le32toh(msg->rm_devicevchdl));
764
765         rval = urndis_ctrl_send(sc, msg, len);
766
767         if (rval != RNDIS_STATUS_SUCCESS) {
768                 DPRINTF("set failed\n");
769                 return (rval);
770         }
771         if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
772                 DPRINTF("unable to get set response\n");
773                 return (RNDIS_STATUS_FAILURE);
774         }
775         rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
776         if (rval != RNDIS_STATUS_SUCCESS)
777                 DPRINTF("set failed 0x%x\n", rval);
778
779         return (rval);
780 }
781
782 static void
783 urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
784 {
785         struct urndis_softc *sc = usbd_xfer_softc(xfer);
786         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
787         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
788         struct urndis_packet_msg msg;
789         struct mbuf *m;
790         int actlen;
791         int aframes;
792         int offset;
793
794         switch (USB_GET_STATE(xfer)) {
795         case USB_ST_TRANSFERRED:
796
797                 usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
798
799                 DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes);
800
801                 for (offset = 0; actlen >= (uint32_t)sizeof(msg);) {
802
803                         /* copy out header */
804                         usbd_copy_out(pc, offset, &msg, sizeof(msg));
805
806                         if (le32toh(0x1234567U) != 0x1234567U) {
807                                 /* swap endianness */
808                                 msg.rm_type = le32toh(msg.rm_type);
809                                 msg.rm_len = le32toh(msg.rm_len);
810                                 msg.rm_dataoffset = le32toh(msg.rm_dataoffset);
811                                 msg.rm_datalen = le32toh(msg.rm_datalen);
812                                 msg.rm_oobdataoffset = le32toh(msg.rm_oobdataoffset);
813                                 msg.rm_oobdatalen = le32toh(msg.rm_oobdatalen);
814                                 msg.rm_oobdataelements = le32toh(msg.rm_oobdataelements);
815                                 msg.rm_pktinfooffset = le32toh(msg.rm_pktinfooffset);
816                                 msg.rm_pktinfolen = le32toh(msg.rm_pktinfolen);
817                                 msg.rm_vchandle = le32toh(msg.rm_vchandle);
818                                 msg.rm_reserved = le32toh(msg.rm_reserved);
819                         }
820
821                         DPRINTF("len %u data(off:%u len:%u) "
822                             "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
823                             msg.rm_len, msg.rm_dataoffset, msg.rm_datalen,
824                             msg.rm_oobdataoffset, msg.rm_oobdatalen,
825                             msg.rm_oobdataelements, msg.rm_pktinfooffset,
826                             msg.rm_pktinfooffset);
827
828                         /* sanity check the RNDIS header */
829                         if (msg.rm_type != REMOTE_NDIS_PACKET_MSG) {
830                                 DPRINTF("invalid type 0x%x != 0x%x\n",
831                                     msg.rm_type, REMOTE_NDIS_PACKET_MSG);
832                                 goto tr_setup;
833                         } else if (msg.rm_len < (uint32_t)sizeof(msg)) {
834                                 DPRINTF("invalid msg len %u < %u\n",
835                                     msg.rm_len, (unsigned)sizeof(msg));
836                                 goto tr_setup;
837                         } else if (msg.rm_len > (uint32_t)actlen) {
838                                 DPRINTF("invalid msg len %u > buffer "
839                                     "len %u\n", msg.rm_len, actlen);
840                                 goto tr_setup;
841                         } else if (msg.rm_dataoffset >= (uint32_t)actlen) {
842                                 DPRINTF("invalid msg dataoffset %u > buffer "
843                                     "dataoffset %u\n", msg.rm_dataoffset, actlen);
844                                 goto tr_setup;
845                         } else if (msg.rm_datalen > (uint32_t)actlen) {
846                                 DPRINTF("invalid msg datalen %u > buffer "
847                                     "datalen %u\n", msg.rm_datalen, actlen);
848                                 goto tr_setup;
849                         } else if ((msg.rm_dataoffset + msg.rm_datalen +
850                             (uint32_t)__offsetof(struct urndis_packet_msg,
851                             rm_dataoffset)) > (uint32_t)actlen) {
852                                 DPRINTF("invalid dataoffset %u larger than %u\n",
853                                     msg.rm_dataoffset + msg.rm_datalen +
854                                     (uint32_t)__offsetof(struct urndis_packet_msg,
855                                     rm_dataoffset), actlen);
856                                 goto tr_setup;
857                         } else if (msg.rm_datalen < (uint32_t)sizeof(struct ether_header)) {
858                                 ifp->if_ierrors++;
859                                 DPRINTF("invalid ethernet size "
860                                     "%u < %u\n", msg.rm_datalen, (unsigned)sizeof(struct ether_header));
861                                 goto tr_setup;
862                         } else if (msg.rm_datalen > (uint32_t)MCLBYTES) {
863                                 ifp->if_ierrors++;
864                                 DPRINTF("invalid ethernet size "
865                                     "%u > %u\n",
866                                     msg.rm_datalen, (unsigned)MCLBYTES);
867                                 goto tr_setup;
868                         } else if (msg.rm_datalen > (uint32_t)(MHLEN - ETHER_ALIGN)) {
869                                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
870                         } else {
871                                 m = m_gethdr(M_NOWAIT, MT_DATA);
872                         }
873
874                         /* check if we have a buffer */
875                         if (m != NULL) {
876                                 m_adj(m, ETHER_ALIGN);
877
878                                 usbd_copy_out(pc, offset + msg.rm_dataoffset +
879                                     __offsetof(struct urndis_packet_msg,
880                                     rm_dataoffset), m->m_data, msg.rm_datalen);
881
882                                 /* enqueue */
883                                 uether_rxmbuf(&sc->sc_ue, m, msg.rm_datalen);
884                         } else {
885                                 ifp->if_ierrors++;
886                         }
887                         offset += msg.rm_len;
888                         actlen -= msg.rm_len;
889                 }
890
891         case USB_ST_SETUP:
892 tr_setup:
893                 usbd_xfer_set_frame_len(xfer, 0, RNDIS_RX_MAXLEN);
894                 usbd_xfer_set_frames(xfer, 1);
895                 usbd_transfer_submit(xfer);
896                 uether_rxflush(&sc->sc_ue);     /* must be last */
897                 break;
898
899         default:                        /* Error */
900                 DPRINTFN(1, "error = %s\n", usbd_errstr(error));
901
902                 if (error != USB_ERR_CANCELLED) {
903                         /* try to clear stall first */
904                         usbd_xfer_set_stall(xfer);
905                         usbd_xfer_set_frames(xfer, 0);
906                         usbd_transfer_submit(xfer);
907                 }
908                 break;
909         }
910 }
911
912 static void
913 urndis_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
914 {
915         struct urndis_packet_msg msg;
916         struct urndis_softc *sc = usbd_xfer_softc(xfer);
917         struct ifnet *ifp = uether_getifp(&sc->sc_ue);
918         struct mbuf *m;
919         unsigned x;
920         int actlen;
921         int aframes;
922
923         usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
924
925         DPRINTFN(1, "\n");
926
927         switch (USB_GET_STATE(xfer)) {
928         case USB_ST_TRANSFERRED:
929                 DPRINTFN(11, "%u bytes in %u frames\n", actlen, aframes);
930
931                 ifp->if_opackets++;
932
933                 /* FALLTHROUGH */
934         case USB_ST_SETUP:
935 tr_setup:
936                 memset(&msg, 0, sizeof(msg));
937
938                 for (x = 0; x != RNDIS_TX_FRAMES_MAX; x++) {
939                         struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, x);
940
941                         usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x);
942
943         next_pkt:
944                         m = ifq_dequeue(&ifp->if_snd);
945
946                         if (m == NULL)
947                                 break;
948
949                         if ((m->m_pkthdr.len + sizeof(msg)) > RNDIS_TX_MAXLEN) {
950                                 DPRINTF("Too big packet\n");
951                                 ifp->if_oerrors++;
952
953                                 /* Free buffer */
954                                 m_freem(m);
955                                 goto next_pkt;
956                         }
957                         msg.rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
958                         msg.rm_len = htole32(sizeof(msg) + m->m_pkthdr.len);
959
960                         msg.rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
961                         msg.rm_datalen = htole32(m->m_pkthdr.len);
962
963                         /* copy in all data */
964                         usbd_copy_in(pc, 0, &msg, sizeof(msg));
965                         usbd_m_copy_in(pc, sizeof(msg), m, 0, m->m_pkthdr.len);
966                         usbd_xfer_set_frame_len(xfer, x, sizeof(msg) + m->m_pkthdr.len);
967
968                         /*
969                          * If there's a BPF listener, bounce a copy of
970                          * this frame to him:
971                          */
972                         BPF_MTAP(ifp, m);
973
974                         /* Free buffer */
975                         m_freem(m);
976                 }
977                 if (x != 0) {
978                         usbd_xfer_set_frames(xfer, x);
979                         usbd_transfer_submit(xfer);
980                 }
981                 break;
982
983         default:                        /* Error */
984                 DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error));
985
986                 /* count output errors */
987                 ifp->if_oerrors++;
988
989                 if (error != USB_ERR_CANCELLED) {
990                         /* try to clear stall first */
991                         usbd_xfer_set_stall(xfer);
992                         goto tr_setup;
993                 }
994                 break;
995         }
996 }
997
998 static void
999 urndis_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
1000 {
1001         int actlen;
1002
1003         usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1004
1005         switch (USB_GET_STATE(xfer)) {
1006         case USB_ST_TRANSFERRED:
1007
1008                 DPRINTF("Received %d bytes\n", actlen);
1009
1010                 /* TODO: decode some indications */
1011
1012                 /* FALLTHROUGH */
1013         case USB_ST_SETUP:
1014 tr_setup:
1015                 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1016                 usbd_transfer_submit(xfer);
1017                 break;
1018
1019         default:                        /* Error */
1020                 if (error != USB_ERR_CANCELLED) {
1021                         /* start clear stall */
1022                         usbd_xfer_set_stall(xfer);
1023                         goto tr_setup;
1024                 }
1025                 break;
1026         }
1027 }