1 /* $OpenBSD: if_urndis.c,v 1.74 2024/05/23 03:21:09 jsg 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 * All rights reserved.
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 #include "bpfilter.h"
23
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/sockio.h>
27 #include <sys/mbuf.h>
28
29 #include <sys/device.h>
30
31 #include <machine/bus.h>
32
33 #include <net/if.h>
34
35 #if NBPFILTER > 0
36 #include <net/bpf.h>
37 #endif
38
39 #include <netinet/in.h>
40 #include <netinet/if_ether.h>
41
42 #include <dev/usb/usb.h>
43 #include <dev/usb/usbdi.h>
44 #include <dev/usb/usbdevs.h>
45
46 #include <dev/rndis.h>
47
48 #include <dev/usb/if_urndisreg.h>
49
50 #ifdef URNDIS_DEBUG
51 #define DPRINTF(x) do { printf x; } while (0)
52 #else
53 #define DPRINTF(x)
54 #endif
55
56 #define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
57
58 int urndis_newbuf(struct urndis_softc *, struct urndis_chain *);
59
60 int urndis_ioctl(struct ifnet *, u_long, caddr_t);
61 #if 0
62 void urndis_watchdog(struct ifnet *);
63 #endif
64
65 void urndis_start(struct ifnet *);
66 void urndis_rxeof(struct usbd_xfer *, void *, usbd_status);
67 void urndis_txeof(struct usbd_xfer *, void *, usbd_status);
68 int urndis_rx_list_init(struct urndis_softc *);
69 int urndis_tx_list_init(struct urndis_softc *);
70
71 void urndis_init(struct urndis_softc *);
72 void urndis_stop(struct urndis_softc *);
73
74 usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
75 uint16_t, uint16_t, void *, size_t);
76 usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t);
77 struct rndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *);
78
79 u_int32_t urndis_ctrl_handle(struct urndis_softc *,
80 struct rndis_comp_hdr *, void **, size_t *);
81 u_int32_t urndis_ctrl_handle_init(struct urndis_softc *,
82 const struct rndis_comp_hdr *);
83 u_int32_t urndis_ctrl_handle_query(struct urndis_softc *,
84 const struct rndis_comp_hdr *, void **, size_t *);
85 u_int32_t urndis_ctrl_handle_reset(struct urndis_softc *,
86 const struct rndis_comp_hdr *);
87 u_int32_t urndis_ctrl_handle_status(struct urndis_softc *,
88 const struct rndis_comp_hdr *);
89
90 u_int32_t urndis_ctrl_init(struct urndis_softc *);
91 u_int32_t urndis_ctrl_halt(struct urndis_softc *);
92 u_int32_t urndis_ctrl_query(struct urndis_softc *, u_int32_t, void *, size_t,
93 void **, size_t *);
94 u_int32_t urndis_ctrl_set(struct urndis_softc *, u_int32_t, void *, size_t);
95 u_int32_t urndis_ctrl_set_param(struct urndis_softc *, const char *, u_int32_t,
96 void *, size_t);
97 #if 0
98 u_int32_t urndis_ctrl_reset(struct urndis_softc *);
99 u_int32_t urndis_ctrl_keepalive(struct urndis_softc *);
100 #endif
101
102 int urndis_encap(struct urndis_softc *, struct mbuf *, int);
103 void urndis_decap(struct urndis_softc *, struct urndis_chain *, u_int32_t);
104
105 const struct urndis_class *urndis_lookup(usb_interface_descriptor_t *);
106
107 int urndis_match(struct device *, void *, void *);
108 void urndis_attach(struct device *, struct device *, void *);
109 int urndis_detach(struct device *, int);
110
111 struct cfdriver urndis_cd = {
112 NULL, "urndis", DV_IFNET
113 };
114
115 const struct cfattach urndis_ca = {
116 sizeof(struct urndis_softc), urndis_match, urndis_attach, urndis_detach
117 };
118
119 const struct urndis_class {
120 u_int8_t class;
121 u_int8_t subclass;
122 u_int8_t protocol;
123 const char *typestr;
124 } urndis_class[] = {
125 { UICLASS_CDC, UISUBCLASS_ABSTRACT_CONTROL_MODEL, 0xff, "Vendor" },
126 { UICLASS_WIRELESS, UISUBCLASS_RF, UIPROTO_RNDIS, "RNDIS" },
127 { UICLASS_MISC, UISUBCLASS_SYNC, UIPROTO_ACTIVESYNC, "Activesync" }
128 };
129
130 usbd_status
urndis_ctrl_msg(struct urndis_softc * sc,uint8_t rt,uint8_t r,uint16_t index,uint16_t value,void * buf,size_t buflen)131 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
132 uint16_t index, uint16_t value, void *buf, size_t buflen)
133 {
134 usb_device_request_t req;
135
136 req.bmRequestType = rt;
137 req.bRequest = r;
138 USETW(req.wValue, value);
139 USETW(req.wIndex, index);
140 USETW(req.wLength, buflen);
141
142 return usbd_do_request(sc->sc_udev, &req, buf);
143 }
144
145 usbd_status
urndis_ctrl_send(struct urndis_softc * sc,void * buf,size_t len)146 urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len)
147 {
148 usbd_status err;
149
150 if (usbd_is_dying(sc->sc_udev))
151 return(0);
152
153 err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
154 sc->sc_ifaceno_ctl, 0, buf, len);
155
156 if (err != USBD_NORMAL_COMPLETION)
157 printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
158
159 return err;
160 }
161
162 struct rndis_comp_hdr *
urndis_ctrl_recv(struct urndis_softc * sc)163 urndis_ctrl_recv(struct urndis_softc *sc)
164 {
165 #define RNDIS_RESPONSE_LEN 0x400
166 struct rndis_comp_hdr *hdr;
167 char *buf;
168 usbd_status err;
169
170 buf = malloc(RNDIS_RESPONSE_LEN, M_TEMP, M_WAITOK | M_CANFAIL);
171 if (buf == NULL) {
172 printf("%s: out of memory\n", DEVNAME(sc));
173 return NULL;
174 }
175
176 err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
177 sc->sc_ifaceno_ctl, 0, buf, RNDIS_RESPONSE_LEN);
178
179 if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) {
180 printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
181 free(buf, M_TEMP, RNDIS_RESPONSE_LEN);
182 return NULL;
183 }
184
185 hdr = (struct rndis_comp_hdr *)buf;
186 DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n",
187 DEVNAME(sc),
188 letoh32(hdr->rm_type),
189 letoh32(hdr->rm_len)));
190
191 if (letoh32(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
192 printf("%s: ctrl message error: wrong size %u > %u\n",
193 DEVNAME(sc),
194 letoh32(hdr->rm_len),
195 RNDIS_RESPONSE_LEN);
196 free(buf, M_TEMP, RNDIS_RESPONSE_LEN);
197 return NULL;
198 }
199
200 return hdr;
201 }
202
203 u_int32_t
urndis_ctrl_handle(struct urndis_softc * sc,struct rndis_comp_hdr * hdr,void ** buf,size_t * bufsz)204 urndis_ctrl_handle(struct urndis_softc *sc, struct rndis_comp_hdr *hdr,
205 void **buf, size_t *bufsz)
206 {
207 u_int32_t rval;
208
209 DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc)));
210
211 if (buf && bufsz) {
212 *buf = NULL;
213 *bufsz = 0;
214 }
215
216 switch (letoh32(hdr->rm_type)) {
217 case REMOTE_NDIS_INITIALIZE_CMPLT:
218 rval = urndis_ctrl_handle_init(sc, hdr);
219 break;
220
221 case REMOTE_NDIS_QUERY_CMPLT:
222 rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
223 break;
224
225 case REMOTE_NDIS_RESET_CMPLT:
226 rval = urndis_ctrl_handle_reset(sc, hdr);
227 break;
228
229 case REMOTE_NDIS_KEEPALIVE_CMPLT:
230 case REMOTE_NDIS_SET_CMPLT:
231 rval = letoh32(hdr->rm_status);
232 break;
233
234 case REMOTE_NDIS_INDICATE_STATUS_MSG:
235 rval = urndis_ctrl_handle_status(sc, hdr);
236 break;
237
238 default:
239 printf("%s: ctrl message error: unknown event 0x%x\n",
240 DEVNAME(sc), letoh32(hdr->rm_type));
241 rval = RNDIS_STATUS_FAILURE;
242 }
243
244 free(hdr, M_TEMP, RNDIS_RESPONSE_LEN);
245
246 return rval;
247 }
248
249 u_int32_t
urndis_ctrl_handle_init(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr)250 urndis_ctrl_handle_init(struct urndis_softc *sc,
251 const struct rndis_comp_hdr *hdr)
252 {
253 const struct rndis_init_comp *msg;
254
255 msg = (struct rndis_init_comp *) hdr;
256
257 DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
258 "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
259 "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
260 DEVNAME(sc),
261 letoh32(msg->rm_len),
262 letoh32(msg->rm_rid),
263 letoh32(msg->rm_status),
264 letoh32(msg->rm_ver_major),
265 letoh32(msg->rm_ver_minor),
266 letoh32(msg->rm_devflags),
267 letoh32(msg->rm_medium),
268 letoh32(msg->rm_pktmaxcnt),
269 letoh32(msg->rm_pktmaxsz),
270 letoh32(msg->rm_align),
271 letoh32(msg->rm_aflistoffset),
272 letoh32(msg->rm_aflistsz)));
273
274 if (letoh32(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
275 printf("%s: init failed 0x%x\n",
276 DEVNAME(sc),
277 letoh32(msg->rm_status));
278
279 return letoh32(msg->rm_status);
280 }
281
282 if (letoh32(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
283 printf("%s: wrong device type (current type: 0x%x)\n",
284 DEVNAME(sc),
285 letoh32(msg->rm_devflags));
286
287 return RNDIS_STATUS_FAILURE;
288 }
289
290 if (letoh32(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
291 printf("%s: medium not 802.3 (current medium: 0x%x)\n",
292 DEVNAME(sc), letoh32(msg->rm_medium));
293
294 return RNDIS_STATUS_FAILURE;
295 }
296
297 sc->sc_lim_pktsz = letoh32(msg->rm_pktmaxsz);
298
299 return letoh32(msg->rm_status);
300 }
301
302 u_int32_t
urndis_ctrl_handle_query(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr,void ** buf,size_t * bufsz)303 urndis_ctrl_handle_query(struct urndis_softc *sc,
304 const struct rndis_comp_hdr *hdr, void **buf, size_t *bufsz)
305 {
306 const struct rndis_query_comp *msg;
307
308 msg = (struct rndis_query_comp *) hdr;
309
310 DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x "
311 "buflen %u bufoff %u\n",
312 DEVNAME(sc),
313 letoh32(msg->rm_len),
314 letoh32(msg->rm_rid),
315 letoh32(msg->rm_status),
316 letoh32(msg->rm_infobuflen),
317 letoh32(msg->rm_infobufoffset)));
318
319 if (buf && bufsz) {
320 *buf = NULL;
321 *bufsz = 0;
322 }
323
324 if (letoh32(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
325 printf("%s: query failed 0x%x\n",
326 DEVNAME(sc),
327 letoh32(msg->rm_status));
328
329 return letoh32(msg->rm_status);
330 }
331
332 if (letoh32(msg->rm_infobuflen) + letoh32(msg->rm_infobufoffset) +
333 RNDIS_HEADER_OFFSET > letoh32(msg->rm_len)) {
334 printf("%s: ctrl message error: invalid query info "
335 "len/offset/end_position(%u/%u/%zu) -> "
336 "go out of buffer limit %u\n",
337 DEVNAME(sc),
338 letoh32(msg->rm_infobuflen),
339 letoh32(msg->rm_infobufoffset),
340 letoh32(msg->rm_infobuflen) +
341 letoh32(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
342 letoh32(msg->rm_len));
343 return RNDIS_STATUS_FAILURE;
344 }
345
346 if (buf && bufsz) {
347 *buf = malloc(letoh32(msg->rm_infobuflen),
348 M_TEMP, M_WAITOK | M_CANFAIL);
349 if (*buf == NULL) {
350 printf("%s: out of memory\n", DEVNAME(sc));
351 return RNDIS_STATUS_FAILURE;
352 } else {
353 char *p;
354 *bufsz = letoh32(msg->rm_infobuflen);
355
356 p = (char *)&msg->rm_rid;
357 p += letoh32(msg->rm_infobufoffset);
358 memcpy(*buf, p, letoh32(msg->rm_infobuflen));
359 }
360 }
361
362 return letoh32(msg->rm_status);
363 }
364
365 u_int32_t
urndis_ctrl_handle_reset(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr)366 urndis_ctrl_handle_reset(struct urndis_softc *sc,
367 const struct rndis_comp_hdr *hdr)
368 {
369 const struct rndis_reset_comp *msg;
370 u_int32_t rval;
371
372 msg = (struct rndis_reset_comp *) hdr;
373
374 rval = letoh32(msg->rm_status);
375
376 DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x "
377 "adrreset %u\n",
378 DEVNAME(sc),
379 letoh32(msg->rm_len),
380 rval,
381 letoh32(msg->rm_adrreset)));
382
383 if (rval != RNDIS_STATUS_SUCCESS) {
384 printf("%s: reset failed 0x%x\n", DEVNAME(sc), rval);
385 return rval;
386 }
387
388 if (letoh32(msg->rm_adrreset) != 0) {
389 u_int32_t filter;
390
391 filter = htole32(sc->sc_filter);
392 rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
393 &filter, sizeof(filter));
394 if (rval != RNDIS_STATUS_SUCCESS) {
395 printf("%s: unable to reset data filters\n",
396 DEVNAME(sc));
397 return rval;
398 }
399 }
400
401 return rval;
402 }
403
404 u_int32_t
urndis_ctrl_handle_status(struct urndis_softc * sc,const struct rndis_comp_hdr * hdr)405 urndis_ctrl_handle_status(struct urndis_softc *sc,
406 const struct rndis_comp_hdr *hdr)
407 {
408 const struct rndis_status_msg *msg;
409 u_int32_t rval;
410
411 msg = (struct rndis_status_msg *)hdr;
412
413 rval = letoh32(msg->rm_status);
414
415 DPRINTF(("%s: urndis_ctrl_handle_status: len %u status 0x%x "
416 "stbuflen %u\n",
417 DEVNAME(sc),
418 letoh32(msg->rm_len),
419 rval,
420 letoh32(msg->rm_stbuflen)));
421
422 switch (rval) {
423 case RNDIS_STATUS_MEDIA_CONNECT:
424 case RNDIS_STATUS_MEDIA_DISCONNECT:
425 case RNDIS_STATUS_OFFLOAD_CURRENT_CONFIG:
426 rval = RNDIS_STATUS_SUCCESS;
427 break;
428
429 default:
430 printf("%s: status 0x%x\n", DEVNAME(sc), rval);
431 }
432
433 return rval;
434 }
435
436 u_int32_t
urndis_ctrl_init(struct urndis_softc * sc)437 urndis_ctrl_init(struct urndis_softc *sc)
438 {
439 struct rndis_init_req *msg;
440 u_int32_t rval;
441 struct rndis_comp_hdr *hdr;
442
443 msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK | M_CANFAIL);
444 if (msg == NULL) {
445 printf("%s: out of memory\n", DEVNAME(sc));
446 return RNDIS_STATUS_FAILURE;
447 }
448
449 msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
450 msg->rm_len = htole32(sizeof(*msg));
451 msg->rm_rid = htole32(0);
452 msg->rm_ver_major = htole32(1);
453 msg->rm_ver_minor = htole32(1);
454 msg->rm_max_xfersz = htole32(RNDIS_BUFSZ);
455
456 DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u "
457 "ver_minor %u max_xfersz %u\n",
458 DEVNAME(sc),
459 letoh32(msg->rm_type),
460 letoh32(msg->rm_len),
461 letoh32(msg->rm_rid),
462 letoh32(msg->rm_ver_major),
463 letoh32(msg->rm_ver_minor),
464 letoh32(msg->rm_max_xfersz)));
465
466 rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
467 free(msg, M_TEMP, sizeof *msg);
468
469 if (rval != RNDIS_STATUS_SUCCESS) {
470 printf("%s: init failed\n", DEVNAME(sc));
471 return rval;
472 }
473
474 if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
475 printf("%s: unable to get init response\n", DEVNAME(sc));
476 return RNDIS_STATUS_FAILURE;
477 }
478 rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
479
480 return rval;
481 }
482
483 u_int32_t
urndis_ctrl_halt(struct urndis_softc * sc)484 urndis_ctrl_halt(struct urndis_softc *sc)
485 {
486 struct rndis_halt_req *msg;
487 u_int32_t rval;
488
489 msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK | M_CANFAIL);
490 if (msg == NULL) {
491 printf("%s: out of memory\n", DEVNAME(sc));
492 return RNDIS_STATUS_FAILURE;
493 }
494
495 msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG);
496 msg->rm_len = htole32(sizeof(*msg));
497 msg->rm_rid = 0;
498
499 DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n",
500 DEVNAME(sc),
501 letoh32(msg->rm_type),
502 letoh32(msg->rm_len),
503 letoh32(msg->rm_rid)));
504
505 rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
506 free(msg, M_TEMP, sizeof *msg);
507
508 if (rval != RNDIS_STATUS_SUCCESS)
509 printf("%s: halt failed\n", DEVNAME(sc));
510
511 return rval;
512 }
513
514 u_int32_t
urndis_ctrl_query(struct urndis_softc * sc,u_int32_t oid,void * qbuf,size_t qlen,void ** rbuf,size_t * rbufsz)515 urndis_ctrl_query(struct urndis_softc *sc, u_int32_t oid,
516 void *qbuf, size_t qlen,
517 void **rbuf, size_t *rbufsz)
518 {
519 struct rndis_query_req *msg;
520 u_int32_t rval;
521 struct rndis_comp_hdr *hdr;
522
523 msg = malloc(sizeof(*msg) + qlen, M_TEMP, M_WAITOK | M_CANFAIL);
524 if (msg == NULL) {
525 printf("%s: out of memory\n", DEVNAME(sc));
526 return RNDIS_STATUS_FAILURE;
527 }
528
529 msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
530 msg->rm_len = htole32(sizeof(*msg) + qlen);
531 msg->rm_rid = 0; /* XXX */
532 msg->rm_oid = htole32(oid);
533 msg->rm_infobuflen = htole32(qlen);
534 if (qlen != 0) {
535 msg->rm_infobufoffset = htole32(20);
536 memcpy((char*)msg + 20, qbuf, qlen);
537 } else
538 msg->rm_infobufoffset = 0;
539 msg->rm_devicevchdl = 0;
540
541 DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x "
542 "infobuflen %u infobufoffset %u devicevchdl %u\n",
543 DEVNAME(sc),
544 letoh32(msg->rm_type),
545 letoh32(msg->rm_len),
546 letoh32(msg->rm_rid),
547 letoh32(msg->rm_oid),
548 letoh32(msg->rm_infobuflen),
549 letoh32(msg->rm_infobufoffset),
550 letoh32(msg->rm_devicevchdl)));
551
552 rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
553 free(msg, M_TEMP, sizeof *msg + qlen);
554
555 if (rval != RNDIS_STATUS_SUCCESS) {
556 printf("%s: query failed\n", DEVNAME(sc));
557 return rval;
558 }
559
560 if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
561 printf("%s: unable to get query response\n", DEVNAME(sc));
562 return RNDIS_STATUS_FAILURE;
563 }
564 rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
565
566 return rval;
567 }
568
569 u_int32_t
urndis_ctrl_set(struct urndis_softc * sc,u_int32_t oid,void * buf,size_t len)570 urndis_ctrl_set(struct urndis_softc *sc, u_int32_t oid, void *buf, size_t len)
571 {
572 struct rndis_set_req *msg;
573 u_int32_t rval;
574 struct rndis_comp_hdr *hdr;
575
576 msg = malloc(sizeof(*msg) + len, M_TEMP, M_WAITOK | M_CANFAIL);
577 if (msg == NULL) {
578 printf("%s: out of memory\n", DEVNAME(sc));
579 return RNDIS_STATUS_FAILURE;
580 }
581
582 msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
583 msg->rm_len = htole32(sizeof(*msg) + len);
584 msg->rm_rid = 0; /* XXX */
585 msg->rm_oid = htole32(oid);
586 msg->rm_infobuflen = htole32(len);
587 if (len != 0) {
588 msg->rm_infobufoffset = htole32(20);
589 memcpy((char*)msg + 28, buf, len);
590 } else
591 msg->rm_infobufoffset = 0;
592 msg->rm_devicevchdl = 0;
593
594 DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x "
595 "infobuflen %u infobufoffset %u devicevchdl %u\n",
596 DEVNAME(sc),
597 letoh32(msg->rm_type),
598 letoh32(msg->rm_len),
599 letoh32(msg->rm_rid),
600 letoh32(msg->rm_oid),
601 letoh32(msg->rm_infobuflen),
602 letoh32(msg->rm_infobufoffset),
603 letoh32(msg->rm_devicevchdl)));
604
605 rval = urndis_ctrl_send(sc, msg, sizeof(*msg) + len);
606 free(msg, M_TEMP, sizeof *msg + len);
607
608 if (rval != RNDIS_STATUS_SUCCESS) {
609 printf("%s: set failed\n", DEVNAME(sc));
610 return rval;
611 }
612
613 if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
614 printf("%s: unable to get set response\n", DEVNAME(sc));
615 return RNDIS_STATUS_FAILURE;
616 }
617 rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
618 if (rval != RNDIS_STATUS_SUCCESS)
619 printf("%s: set failed 0x%x\n", DEVNAME(sc), rval);
620
621 return rval;
622 }
623
624 u_int32_t
urndis_ctrl_set_param(struct urndis_softc * sc,const char * name,u_int32_t type,void * buf,size_t len)625 urndis_ctrl_set_param(struct urndis_softc *sc,
626 const char *name,
627 u_int32_t type,
628 void *buf,
629 size_t len)
630 {
631 struct rndis_set_parameter *param;
632 u_int32_t rval;
633 size_t namelen, tlen;
634
635 if (name)
636 namelen = strlen(name);
637 else
638 namelen = 0;
639 tlen = sizeof(*param) + len + namelen;
640 param = malloc(tlen, M_TEMP, M_WAITOK | M_CANFAIL);
641 if (param == NULL) {
642 printf("%s: out of memory\n", DEVNAME(sc));
643 return RNDIS_STATUS_FAILURE;
644 }
645
646 param->rm_namelen = htole32(namelen);
647 param->rm_valuelen = htole32(len);
648 param->rm_type = htole32(type);
649 if (namelen != 0) {
650 param->rm_nameoffset = htole32(20);
651 memcpy(param + 20, name, namelen);
652 } else
653 param->rm_nameoffset = 0;
654 if (len != 0) {
655 param->rm_valueoffset = htole32(20 + namelen);
656 memcpy(param + 20 + namelen, buf, len);
657 } else
658 param->rm_valueoffset = 0;
659
660 DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u "
661 "type 0x%x valueoffset %u valuelen %u\n",
662 DEVNAME(sc),
663 letoh32(param->rm_nameoffset),
664 letoh32(param->rm_namelen),
665 letoh32(param->rm_type),
666 letoh32(param->rm_valueoffset),
667 letoh32(param->rm_valuelen)));
668
669 rval = urndis_ctrl_set(sc, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen);
670 free(param, M_TEMP, tlen);
671 if (rval != RNDIS_STATUS_SUCCESS)
672 printf("%s: set param failed 0x%x\n", DEVNAME(sc), rval);
673
674 return rval;
675 }
676
677 #if 0
678 /* XXX : adrreset, get it from response */
679 u_int32_t
680 urndis_ctrl_reset(struct urndis_softc *sc)
681 {
682 struct rndis_reset_req *reset;
683 u_int32_t rval;
684 struct rndis_comp_hdr *hdr;
685
686 reset = malloc(sizeof(*reset), M_TEMP, M_WAITOK | M_CANFAIL);
687 if (reset == NULL) {
688 printf("%s: out of memory\n", DEVNAME(sc));
689 return RNDIS_STATUS_FAILURE;
690 }
691
692 reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG);
693 reset->rm_len = htole32(sizeof(*reset));
694 reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
695
696 DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n",
697 DEVNAME(sc),
698 letoh32(reset->rm_type),
699 letoh32(reset->rm_len),
700 letoh32(reset->rm_rid)));
701
702 rval = urndis_ctrl_send(sc, reset, sizeof(*reset));
703 free(reset, M_TEMP, sizeof *reset);
704
705 if (rval != RNDIS_STATUS_SUCCESS) {
706 printf("%s: reset failed\n", DEVNAME(sc));
707 return rval;
708 }
709
710 if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
711 printf("%s: unable to get reset response\n", DEVNAME(sc));
712 return RNDIS_STATUS_FAILURE;
713 }
714 rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
715
716 return rval;
717 }
718
719 u_int32_t
720 urndis_ctrl_keepalive(struct urndis_softc *sc)
721 {
722 struct rndis_keepalive_req *keep;
723 u_int32_t rval;
724 struct rndis_comp_hdr *hdr;
725
726 keep = malloc(sizeof(*keep), M_TEMP, M_WAITOK | M_CANFAIL);
727 if (keep == NULL) {
728 printf("%s: out of memory\n", DEVNAME(sc));
729 return RNDIS_STATUS_FAILURE;
730 }
731
732 keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG);
733 keep->rm_len = htole32(sizeof(*keep));
734 keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
735
736 DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n",
737 DEVNAME(sc),
738 letoh32(keep->rm_type),
739 letoh32(keep->rm_len),
740 letoh32(keep->rm_rid)));
741
742 rval = urndis_ctrl_send(sc, keep, sizeof(*keep));
743 free(keep, M_TEMP, sizeof *keep);
744
745 if (rval != RNDIS_STATUS_SUCCESS) {
746 printf("%s: keepalive failed\n", DEVNAME(sc));
747 return rval;
748 }
749
750 if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
751 printf("%s: unable to get keepalive response\n", DEVNAME(sc));
752 return RNDIS_STATUS_FAILURE;
753 }
754 rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
755 if (rval != RNDIS_STATUS_SUCCESS) {
756 printf("%s: keepalive failed 0x%x\n", DEVNAME(sc), rval);
757 urndis_ctrl_reset(sc);
758 }
759
760 return rval;
761 }
762 #endif
763
764 int
urndis_encap(struct urndis_softc * sc,struct mbuf * m,int idx)765 urndis_encap(struct urndis_softc *sc, struct mbuf *m, int idx)
766 {
767 struct urndis_chain *c;
768 usbd_status err;
769 struct rndis_packet_msg *msg;
770
771 c = &sc->sc_data.sc_tx_chain[idx];
772
773 msg = (struct rndis_packet_msg *)c->sc_buf;
774
775 memset(msg, 0, sizeof(*msg));
776 msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
777 msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len);
778
779 msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
780 msg->rm_datalen = htole32(m->m_pkthdr.len);
781
782 m_copydata(m, 0, m->m_pkthdr.len,
783 ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET));
784
785 DPRINTF(("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n",
786 DEVNAME(sc),
787 letoh32(msg->rm_type),
788 letoh32(msg->rm_len),
789 letoh32(msg->rm_dataoffset),
790 letoh32(msg->rm_datalen)));
791
792 c->sc_mbuf = m;
793
794 usbd_setup_xfer(c->sc_xfer, sc->sc_bulkout_pipe, c, c->sc_buf,
795 letoh32(msg->rm_len), USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 10000,
796 urndis_txeof);
797
798 /* Transmit */
799 err = usbd_transfer(c->sc_xfer);
800 if (err != USBD_IN_PROGRESS) {
801 c->sc_mbuf = NULL;
802 urndis_stop(sc);
803 return(EIO);
804 }
805
806 sc->sc_data.sc_tx_cnt++;
807
808 return(0);
809 }
810
811 void
urndis_decap(struct urndis_softc * sc,struct urndis_chain * c,u_int32_t len)812 urndis_decap(struct urndis_softc *sc, struct urndis_chain *c, u_int32_t len)
813 {
814 struct mbuf *m;
815 struct mbuf_list ml = MBUF_LIST_INITIALIZER();
816 struct rndis_packet_msg *msg;
817 struct ifnet *ifp;
818 int s;
819 int offset;
820
821 ifp = GET_IFP(sc);
822 offset = 0;
823
824 while (len > 1) {
825 msg = (struct rndis_packet_msg *)((char*)c->sc_buf + offset);
826 m = c->sc_mbuf;
827
828 DPRINTF(("%s: urndis_decap buffer size left %u\n", DEVNAME(sc),
829 len));
830
831 if (len < sizeof(*msg)) {
832 printf("%s: urndis_decap invalid buffer len %u < "
833 "minimum header %zu\n",
834 DEVNAME(sc),
835 len,
836 sizeof(*msg));
837 break;
838 }
839
840 DPRINTF(("%s: urndis_decap len %u data(off:%u len:%u) "
841 "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
842 DEVNAME(sc),
843 letoh32(msg->rm_len),
844 letoh32(msg->rm_dataoffset),
845 letoh32(msg->rm_datalen),
846 letoh32(msg->rm_oobdataoffset),
847 letoh32(msg->rm_oobdatalen),
848 letoh32(msg->rm_oobdataelements),
849 letoh32(msg->rm_pktinfooffset),
850 letoh32(msg->rm_pktinfooffset)));
851
852 if (letoh32(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) {
853 printf("%s: urndis_decap invalid type 0x%x != 0x%x\n",
854 DEVNAME(sc),
855 letoh32(msg->rm_type),
856 REMOTE_NDIS_PACKET_MSG);
857 break;
858 }
859 if (letoh32(msg->rm_len) < sizeof(*msg)) {
860 printf("%s: urndis_decap invalid msg len %u < %zu\n",
861 DEVNAME(sc),
862 letoh32(msg->rm_len),
863 sizeof(*msg));
864 break;
865 }
866 if (letoh32(msg->rm_len) > len) {
867 printf("%s: urndis_decap invalid msg len %u > buffer "
868 "len %u\n",
869 DEVNAME(sc),
870 letoh32(msg->rm_len),
871 len);
872 break;
873 }
874
875 if (letoh32(msg->rm_dataoffset) +
876 letoh32(msg->rm_datalen) + RNDIS_HEADER_OFFSET
877 > letoh32(msg->rm_len)) {
878 printf("%s: urndis_decap invalid data "
879 "len/offset/end_position(%u/%u/%zu) -> "
880 "go out of receive buffer limit %u\n",
881 DEVNAME(sc),
882 letoh32(msg->rm_datalen),
883 letoh32(msg->rm_dataoffset),
884 letoh32(msg->rm_dataoffset) +
885 letoh32(msg->rm_datalen) + RNDIS_HEADER_OFFSET,
886 letoh32(msg->rm_len));
887 break;
888 }
889
890 if (letoh32(msg->rm_datalen) < sizeof(struct ether_header)) {
891 ifp->if_ierrors++;
892 DPRINTF(("%s: urndis_decap invalid ethernet size "
893 "%u < %zu\n",
894 DEVNAME(sc),
895 letoh32(msg->rm_datalen),
896 sizeof(struct ether_header)));
897 break;
898 }
899
900 memcpy(mtod(m, char*),
901 ((char*)&msg->rm_dataoffset + letoh32(msg->rm_dataoffset)),
902 letoh32(msg->rm_datalen));
903 m->m_pkthdr.len = m->m_len = letoh32(msg->rm_datalen);
904
905 if (urndis_newbuf(sc, c) == ENOBUFS) {
906 ifp->if_ierrors++;
907 } else {
908 ml_enqueue(&ml, m);
909 }
910
911 offset += letoh32(msg->rm_len);
912 len -= letoh32(msg->rm_len);
913 }
914 if (ml_empty(&ml))
915 return;
916
917 s = splnet();
918 if_input(ifp, &ml);
919 splx(s);
920 }
921
922 int
urndis_newbuf(struct urndis_softc * sc,struct urndis_chain * c)923 urndis_newbuf(struct urndis_softc *sc, struct urndis_chain *c)
924 {
925 struct mbuf *m_new = NULL;
926
927 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
928 if (m_new == NULL) {
929 printf("%s: no memory for rx list -- packet dropped!\n",
930 DEVNAME(sc));
931 return (ENOBUFS);
932 }
933 MCLGET(m_new, M_DONTWAIT);
934 if (!(m_new->m_flags & M_EXT)) {
935 printf("%s: no memory for rx list -- packet dropped!\n",
936 DEVNAME(sc));
937 m_freem(m_new);
938 return (ENOBUFS);
939 }
940 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
941
942 m_adj(m_new, ETHER_ALIGN);
943 c->sc_mbuf = m_new;
944 return (0);
945 }
946
947 int
urndis_rx_list_init(struct urndis_softc * sc)948 urndis_rx_list_init(struct urndis_softc *sc)
949 {
950 struct urndis_cdata *cd;
951 struct urndis_chain *c;
952 int i;
953
954 cd = &sc->sc_data;
955 for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
956 c = &cd->sc_rx_chain[i];
957 c->sc_softc = sc;
958 c->sc_idx = i;
959
960 if (urndis_newbuf(sc, c) == ENOBUFS)
961 return (ENOBUFS);
962
963 if (c->sc_xfer == NULL) {
964 c->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
965 if (c->sc_xfer == NULL)
966 return (ENOBUFS);
967 c->sc_buf = usbd_alloc_buffer(c->sc_xfer,
968 RNDIS_BUFSZ);
969 if (c->sc_buf == NULL)
970 return (ENOBUFS);
971 }
972 }
973
974 return (0);
975 }
976
977 int
urndis_tx_list_init(struct urndis_softc * sc)978 urndis_tx_list_init(struct urndis_softc *sc)
979 {
980 struct urndis_cdata *cd;
981 struct urndis_chain *c;
982 int i;
983
984 cd = &sc->sc_data;
985 for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
986 c = &cd->sc_tx_chain[i];
987 c->sc_softc = sc;
988 c->sc_idx = i;
989 c->sc_mbuf = NULL;
990 if (c->sc_xfer == NULL) {
991 c->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
992 if (c->sc_xfer == NULL)
993 return (ENOBUFS);
994 c->sc_buf = usbd_alloc_buffer(c->sc_xfer,
995 RNDIS_BUFSZ);
996 if (c->sc_buf == NULL)
997 return (ENOBUFS);
998 }
999 }
1000 return (0);
1001 }
1002
1003 int
urndis_ioctl(struct ifnet * ifp,u_long command,caddr_t data)1004 urndis_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1005 {
1006 struct urndis_softc *sc = ifp->if_softc;
1007 int s, error = 0;
1008
1009 if (usbd_is_dying(sc->sc_udev))
1010 return ENXIO;
1011
1012 s = splnet();
1013
1014 switch(command) {
1015 case SIOCSIFADDR:
1016 ifp->if_flags |= IFF_UP;
1017 if (!(ifp->if_flags & IFF_RUNNING))
1018 urndis_init(sc);
1019 break;
1020
1021 case SIOCSIFFLAGS:
1022 if (ifp->if_flags & IFF_UP) {
1023 if (ifp->if_flags & IFF_RUNNING)
1024 error = ENETRESET;
1025 else
1026 urndis_init(sc);
1027 } else {
1028 if (ifp->if_flags & IFF_RUNNING)
1029 urndis_stop(sc);
1030 }
1031 break;
1032
1033 default:
1034 error = ether_ioctl(ifp, &sc->sc_arpcom, command, data);
1035 break;
1036 }
1037
1038 if (error == ENETRESET)
1039 error = 0;
1040
1041 splx(s);
1042 return (error);
1043 }
1044
1045 #if 0
1046 void
1047 urndis_watchdog(struct ifnet *ifp)
1048 {
1049 struct urndis_softc *sc;
1050
1051 sc = ifp->if_softc;
1052
1053 if (usbd_is_dying(sc->sc_udev))
1054 return;
1055
1056 ifp->if_oerrors++;
1057 printf("%s: watchdog timeout\n", DEVNAME(sc));
1058
1059 urndis_ctrl_keepalive(sc);
1060 }
1061 #endif
1062
1063 void
urndis_init(struct urndis_softc * sc)1064 urndis_init(struct urndis_softc *sc)
1065 {
1066 struct ifnet *ifp = GET_IFP(sc);
1067 int i, s;
1068 usbd_status err;
1069
1070 if (urndis_ctrl_init(sc) != RNDIS_STATUS_SUCCESS)
1071 return;
1072
1073 s = splnet();
1074
1075 if (urndis_tx_list_init(sc) == ENOBUFS) {
1076 printf("%s: tx list init failed\n",
1077 DEVNAME(sc));
1078 splx(s);
1079 return;
1080 }
1081
1082 if (urndis_rx_list_init(sc) == ENOBUFS) {
1083 printf("%s: rx list init failed\n",
1084 DEVNAME(sc));
1085 splx(s);
1086 return;
1087 }
1088
1089 err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no,
1090 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
1091 if (err) {
1092 printf("%s: open rx pipe failed: %s\n", DEVNAME(sc),
1093 usbd_errstr(err));
1094 splx(s);
1095 return;
1096 }
1097
1098 err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no,
1099 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
1100 if (err) {
1101 printf("%s: open tx pipe failed: %s\n", DEVNAME(sc),
1102 usbd_errstr(err));
1103 splx(s);
1104 return;
1105 }
1106
1107 for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
1108 struct urndis_chain *c;
1109
1110 c = &sc->sc_data.sc_rx_chain[i];
1111 usbd_setup_xfer(c->sc_xfer, sc->sc_bulkin_pipe, c,
1112 c->sc_buf, RNDIS_BUFSZ,
1113 USBD_SHORT_XFER_OK | USBD_NO_COPY,
1114 USBD_NO_TIMEOUT, urndis_rxeof);
1115 usbd_transfer(c->sc_xfer);
1116 }
1117
1118 ifp->if_flags |= IFF_RUNNING;
1119 ifq_clr_oactive(&ifp->if_snd);
1120
1121 splx(s);
1122 }
1123
1124 void
urndis_stop(struct urndis_softc * sc)1125 urndis_stop(struct urndis_softc *sc)
1126 {
1127 usbd_status err;
1128 struct ifnet *ifp;
1129 int i;
1130
1131 ifp = GET_IFP(sc);
1132 ifp->if_timer = 0;
1133 ifp->if_flags &= ~IFF_RUNNING;
1134 ifq_clr_oactive(&ifp->if_snd);
1135
1136 if (sc->sc_bulkin_pipe != NULL) {
1137 err = usbd_close_pipe(sc->sc_bulkin_pipe);
1138 if (err)
1139 printf("%s: close rx pipe failed: %s\n",
1140 DEVNAME(sc), usbd_errstr(err));
1141 sc->sc_bulkin_pipe = NULL;
1142 }
1143
1144 if (sc->sc_bulkout_pipe != NULL) {
1145 err = usbd_close_pipe(sc->sc_bulkout_pipe);
1146 if (err)
1147 printf("%s: close tx pipe failed: %s\n",
1148 DEVNAME(sc), usbd_errstr(err));
1149 sc->sc_bulkout_pipe = NULL;
1150 }
1151
1152 for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
1153 if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) {
1154 m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf);
1155 sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL;
1156 }
1157 if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) {
1158 usbd_free_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer);
1159 sc->sc_data.sc_rx_chain[i].sc_xfer = NULL;
1160 }
1161 }
1162
1163 for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
1164 if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) {
1165 m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf);
1166 sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL;
1167 }
1168 if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) {
1169 usbd_free_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer);
1170 sc->sc_data.sc_tx_chain[i].sc_xfer = NULL;
1171 }
1172 }
1173 }
1174
1175 void
urndis_start(struct ifnet * ifp)1176 urndis_start(struct ifnet *ifp)
1177 {
1178 struct urndis_softc *sc;
1179 struct mbuf *m_head = NULL;
1180
1181 sc = ifp->if_softc;
1182
1183 if (usbd_is_dying(sc->sc_udev) || ifq_is_oactive(&ifp->if_snd))
1184 return;
1185
1186 m_head = ifq_dequeue(&ifp->if_snd);
1187 if (m_head == NULL)
1188 return;
1189
1190 if (urndis_encap(sc, m_head, 0)) {
1191 m_freem(m_head);
1192 ifq_set_oactive(&ifp->if_snd);
1193 return;
1194 }
1195
1196 /*
1197 * If there's a BPF listener, bounce a copy of this frame
1198 * to him.
1199 */
1200 #if NBPFILTER > 0
1201 if (ifp->if_bpf)
1202 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
1203 #endif
1204
1205 ifq_set_oactive(&ifp->if_snd);
1206
1207 /*
1208 * Set a timeout in case the chip goes out to lunch.
1209 */
1210 ifp->if_timer = 5;
1211
1212 return;
1213 }
1214
1215 void
urndis_rxeof(struct usbd_xfer * xfer,void * priv,usbd_status status)1216 urndis_rxeof(struct usbd_xfer *xfer,
1217 void *priv,
1218 usbd_status status)
1219 {
1220 struct urndis_chain *c;
1221 struct urndis_softc *sc;
1222 struct ifnet *ifp;
1223 u_int32_t total_len;
1224
1225 c = priv;
1226 sc = c->sc_softc;
1227 ifp = GET_IFP(sc);
1228 total_len = 0;
1229
1230 if (usbd_is_dying(sc->sc_udev) || !(ifp->if_flags & IFF_RUNNING))
1231 return;
1232
1233 if (status != USBD_NORMAL_COMPLETION) {
1234 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1235 return;
1236 if (usbd_ratecheck(&sc->sc_rx_notice)) {
1237 DPRINTF(("%s: usb errors on rx: %s\n",
1238 DEVNAME(sc), usbd_errstr(status)));
1239 }
1240 if (status == USBD_STALLED)
1241 usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
1242
1243 ifp->if_ierrors++;
1244 goto done;
1245 }
1246
1247 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
1248 urndis_decap(sc, c, total_len);
1249
1250 done:
1251 /* Setup new transfer. */
1252 usbd_setup_xfer(c->sc_xfer, sc->sc_bulkin_pipe, c, c->sc_buf,
1253 RNDIS_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
1254 urndis_rxeof);
1255 usbd_transfer(c->sc_xfer);
1256 }
1257
1258 void
urndis_txeof(struct usbd_xfer * xfer,void * priv,usbd_status status)1259 urndis_txeof(struct usbd_xfer *xfer,
1260 void *priv,
1261 usbd_status status)
1262 {
1263 struct urndis_chain *c;
1264 struct urndis_softc *sc;
1265 struct ifnet *ifp;
1266 usbd_status err;
1267 int s;
1268
1269 c = priv;
1270 sc = c->sc_softc;
1271 ifp = GET_IFP(sc);
1272
1273 DPRINTF(("%s: urndis_txeof\n", DEVNAME(sc)));
1274
1275 if (usbd_is_dying(sc->sc_udev))
1276 return;
1277
1278 s = splnet();
1279
1280 ifp->if_timer = 0;
1281 ifq_clr_oactive(&ifp->if_snd);
1282
1283 if (status != USBD_NORMAL_COMPLETION) {
1284 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1285 splx(s);
1286 return;
1287 }
1288 ifp->if_oerrors++;
1289 DPRINTF(("%s: usb error on tx: %s\n", DEVNAME(sc),
1290 usbd_errstr(status)));
1291 if (status == USBD_STALLED)
1292 usbd_clear_endpoint_stall_async(sc->sc_bulkout_pipe);
1293 splx(s);
1294 return;
1295 }
1296
1297 usbd_get_xfer_status(c->sc_xfer, NULL, NULL, NULL, &err);
1298
1299 if (c->sc_mbuf != NULL) {
1300 m_freem(c->sc_mbuf);
1301 c->sc_mbuf = NULL;
1302 }
1303
1304 if (err)
1305 ifp->if_oerrors++;
1306
1307 if (ifq_empty(&ifp->if_snd) == 0)
1308 urndis_start(ifp);
1309
1310 splx(s);
1311 }
1312
1313 const struct urndis_class *
urndis_lookup(usb_interface_descriptor_t * id)1314 urndis_lookup(usb_interface_descriptor_t *id)
1315 {
1316 const struct urndis_class *uc;
1317 int i;
1318
1319 uc = urndis_class;
1320 for (i = 0; i < nitems(urndis_class); i++, uc++) {
1321 if (uc->class == id->bInterfaceClass &&
1322 uc->subclass == id->bInterfaceSubClass &&
1323 uc->protocol == id->bInterfaceProtocol)
1324 return (uc);
1325 }
1326 return (NULL);
1327 }
1328
1329 int
urndis_match(struct device * parent,void * match,void * aux)1330 urndis_match(struct device *parent, void *match, void *aux)
1331 {
1332 struct usb_attach_arg *uaa = aux;
1333 usb_interface_descriptor_t *id;
1334
1335 /* Advertises both RNDIS and CDC Ethernet, but RNDIS doesn't work. */
1336 if (uaa->vendor == USB_VENDOR_FUJITSUCOMP &&
1337 uaa->product == USB_PRODUCT_FUJITSUCOMP_VIRTETH)
1338 return (UMATCH_NONE);
1339
1340 if (!uaa->iface)
1341 return (UMATCH_NONE);
1342
1343 id = usbd_get_interface_descriptor(uaa->iface);
1344 if (id == NULL)
1345 return (UMATCH_NONE);
1346
1347 return (urndis_lookup(id) ?
1348 UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO : UMATCH_NONE);
1349 }
1350
1351 void
urndis_attach(struct device * parent,struct device * self,void * aux)1352 urndis_attach(struct device *parent, struct device *self, void *aux)
1353 {
1354 const struct urndis_class *uc;
1355 struct urndis_softc *sc;
1356 struct usb_attach_arg *uaa;
1357 struct ifnet *ifp;
1358 usb_interface_descriptor_t *id;
1359 usb_endpoint_descriptor_t *ed;
1360 usb_config_descriptor_t *cd;
1361 int i, j, altcnt;
1362 int s;
1363 u_char eaddr[ETHER_ADDR_LEN];
1364 void *buf;
1365 size_t bufsz;
1366 u_int32_t filter;
1367
1368 sc = (void *)self;
1369 uaa = aux;
1370
1371 sc->sc_attached = 0;
1372 sc->sc_udev = uaa->device;
1373 id = usbd_get_interface_descriptor(uaa->iface);
1374 sc->sc_ifaceno_ctl = id->bInterfaceNumber;
1375
1376 for (i = 0; i < uaa->nifaces; i++) {
1377 if (usbd_iface_claimed(sc->sc_udev, i))
1378 continue;
1379
1380 if (uaa->ifaces[i] != uaa->iface) {
1381 sc->sc_iface_data = uaa->ifaces[i];
1382 usbd_claim_iface(sc->sc_udev, i);
1383 break;
1384 }
1385 }
1386
1387 if (sc->sc_iface_data == NULL) {
1388 printf("%s: no data interface\n", DEVNAME(sc));
1389 return;
1390 }
1391
1392 uc = urndis_lookup(id);
1393 printf("%s: using %s", DEVNAME(sc), uc->typestr);
1394
1395 id = usbd_get_interface_descriptor(sc->sc_iface_data);
1396 cd = usbd_get_config_descriptor(sc->sc_udev);
1397 altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber);
1398
1399 for (j = 0; j < altcnt; j++) {
1400 if (usbd_set_interface(sc->sc_iface_data, j)) {
1401 printf(": interface alternate setting %u failed\n", j);
1402 return;
1403 }
1404 /* Find endpoints. */
1405 id = usbd_get_interface_descriptor(sc->sc_iface_data);
1406 sc->sc_bulkin_no = sc->sc_bulkout_no = -1;
1407 for (i = 0; i < id->bNumEndpoints; i++) {
1408 ed = usbd_interface2endpoint_descriptor(
1409 sc->sc_iface_data, i);
1410 if (!ed) {
1411 printf(": no descriptor for bulk endpoint "
1412 "%u\n", i);
1413 return;
1414 }
1415 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
1416 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1417 sc->sc_bulkin_no = ed->bEndpointAddress;
1418 }
1419 else if (
1420 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
1421 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
1422 sc->sc_bulkout_no = ed->bEndpointAddress;
1423 }
1424 }
1425
1426 if (sc->sc_bulkin_no != -1 && sc->sc_bulkout_no != -1) {
1427 DPRINTF(("%s: in=0x%x, out=0x%x\n",
1428 DEVNAME(sc),
1429 sc->sc_bulkin_no,
1430 sc->sc_bulkout_no));
1431 goto found;
1432 }
1433 }
1434
1435 if (sc->sc_bulkin_no == -1)
1436 printf(": could not find data bulk in\n");
1437 if (sc->sc_bulkout_no == -1 )
1438 printf(": could not find data bulk out\n");
1439 return;
1440
1441 found:
1442
1443 ifp = GET_IFP(sc);
1444 ifp->if_softc = sc;
1445 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1446 ifp->if_start = urndis_start;
1447 ifp->if_ioctl = urndis_ioctl;
1448 #if 0
1449 ifp->if_watchdog = urndis_watchdog;
1450 #endif
1451
1452 strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
1453
1454 s = splnet();
1455
1456 if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
1457 &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
1458 printf(": unable to get hardware address\n");
1459 splx(s);
1460 return;
1461 }
1462
1463 if (bufsz == ETHER_ADDR_LEN) {
1464 memcpy(eaddr, buf, ETHER_ADDR_LEN);
1465 printf(", address %s\n", ether_sprintf(eaddr));
1466 free(buf, M_TEMP, bufsz);
1467 } else {
1468 printf(", invalid address\n");
1469 free(buf, M_TEMP, bufsz);
1470 splx(s);
1471 return;
1472 }
1473
1474 /* Initialize packet filter */
1475 sc->sc_filter = NDIS_PACKET_TYPE_BROADCAST;
1476 sc->sc_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
1477 filter = htole32(sc->sc_filter);
1478 if (urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, &filter,
1479 sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
1480 printf("%s: unable to set data filters\n", DEVNAME(sc));
1481 splx(s);
1482 return;
1483 }
1484
1485 bcopy(eaddr, (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
1486
1487 if_attach(ifp);
1488 ether_ifattach(ifp);
1489 sc->sc_attached = 1;
1490
1491 splx(s);
1492 }
1493
1494 int
urndis_detach(struct device * self,int flags)1495 urndis_detach(struct device *self, int flags)
1496 {
1497 struct urndis_softc *sc;
1498 struct ifnet *ifp;
1499 int s;
1500
1501 sc = (void*)self;
1502
1503 DPRINTF(("urndis_detach: %s flags %u\n", DEVNAME(sc),
1504 flags));
1505
1506 if (!sc->sc_attached)
1507 return 0;
1508
1509 s = splusb();
1510
1511 ifp = GET_IFP(sc);
1512
1513 if (ifp->if_softc != NULL) {
1514 ether_ifdetach(ifp);
1515 if_detach(ifp);
1516 }
1517
1518 urndis_stop(sc);
1519 sc->sc_attached = 0;
1520
1521 splx(s);
1522
1523 return 0;
1524 }
1525