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