xref: /openbsd-src/sys/dev/usb/if_umb.c (revision c1a45aed656e7d5627c30c92421893a76f370ccb)
1 /*	$OpenBSD: if_umb.c,v 1.49 2022/01/11 10:34:13 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2016 genua mbH
5  * All rights reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * Mobile Broadband Interface Model specification:
22  * https://www.usb.org/sites/default/files/MBIM10Errata1_073013.zip
23  * Compliance testing guide
24  * https://www.usb.org/sites/default/files/MBIM-Compliance-1.0.pdf
25  */
26 #include "bpfilter.h"
27 
28 #include <sys/param.h>
29 #include <sys/mbuf.h>
30 #include <sys/socket.h>
31 #include <sys/systm.h>
32 #include <sys/syslog.h>
33 
34 #if NBPFILTER > 0
35 #include <net/bpf.h>
36 #endif
37 #include <net/if.h>
38 #include <net/if_var.h>
39 #include <net/if_types.h>
40 #include <net/route.h>
41 
42 #include <netinet/in.h>
43 #include <netinet/in_var.h>
44 #include <netinet/ip.h>
45 
46 #ifdef INET6
47 #include <netinet/ip6.h>
48 #include <netinet6/in6_var.h>
49 #include <netinet6/ip6_var.h>
50 #include <netinet6/in6_ifattach.h>
51 #include <netinet6/nd6.h>
52 #endif
53 
54 #include <machine/bus.h>
55 
56 #include <dev/usb/usb.h>
57 #include <dev/usb/usbdi.h>
58 #include <dev/usb/usbdivar.h>
59 #include <dev/usb/usbdi_util.h>
60 #include <dev/usb/usbdevs.h>
61 #include <dev/usb/usbcdc.h>
62 
63 #include <dev/usb/mbim.h>
64 #include <dev/usb/if_umb.h>
65 
66 #ifdef UMB_DEBUG
67 #define DPRINTF(x...)							\
68 		do { if (umb_debug) log(LOG_DEBUG, x); } while (0)
69 
70 #define DPRINTFN(n, x...)						\
71 		do { if (umb_debug >= (n)) log(LOG_DEBUG, x); } while (0)
72 
73 #define DDUMPN(n, b, l)							\
74 		do {							\
75 			if (umb_debug >= (n))				\
76 				umb_dump((b), (l));			\
77 		} while (0)
78 
79 int	 umb_debug = 0;
80 char	*umb_uuid2str(uint8_t [MBIM_UUID_LEN]);
81 void	 umb_dump(void *, int);
82 
83 #else
84 #define DPRINTF(x...)		do { } while (0)
85 #define DPRINTFN(n, x...)	do { } while (0)
86 #define DDUMPN(n, b, l)		do { } while (0)
87 #endif
88 
89 #define DEVNAM(sc)		(((struct umb_softc *)(sc))->sc_dev.dv_xname)
90 
91 /*
92  * State change timeout
93  */
94 #define UMB_STATE_CHANGE_TIMEOUT	30
95 
96 /*
97  * State change flags
98  */
99 #define UMB_NS_DONT_DROP	0x0001	/* do not drop below current state */
100 #define UMB_NS_DONT_RAISE	0x0002	/* do not raise below current state */
101 
102 /*
103  * Diagnostic macros
104  */
105 const struct umb_valdescr umb_regstates[] = MBIM_REGSTATE_DESCRIPTIONS;
106 const struct umb_valdescr umb_dataclasses[] = MBIM_DATACLASS_DESCRIPTIONS;
107 const struct umb_valdescr umb_simstate[] = MBIM_SIMSTATE_DESCRIPTIONS;
108 const struct umb_valdescr umb_messages[] = MBIM_MESSAGES_DESCRIPTIONS;
109 const struct umb_valdescr umb_status[] = MBIM_STATUS_DESCRIPTIONS;
110 const struct umb_valdescr umb_cids[] = MBIM_CID_DESCRIPTIONS;
111 const struct umb_valdescr umb_pktstate[] = MBIM_PKTSRV_STATE_DESCRIPTIONS;
112 const struct umb_valdescr umb_actstate[] = MBIM_ACTIVATION_STATE_DESCRIPTIONS;
113 const struct umb_valdescr umb_error[] = MBIM_ERROR_DESCRIPTIONS;
114 const struct umb_valdescr umb_pintype[] = MBIM_PINTYPE_DESCRIPTIONS;
115 const struct umb_valdescr umb_istate[] = UMB_INTERNAL_STATE_DESCRIPTIONS;
116 
117 #define umb_regstate(c)		umb_val2descr(umb_regstates, (c))
118 #define umb_dataclass(c)	umb_val2descr(umb_dataclasses, (c))
119 #define umb_simstate(s)		umb_val2descr(umb_simstate, (s))
120 #define umb_request2str(m)	umb_val2descr(umb_messages, (m))
121 #define umb_status2str(s)	umb_val2descr(umb_status, (s))
122 #define umb_cid2str(c)		umb_val2descr(umb_cids, (c))
123 #define umb_packet_state(s)	umb_val2descr(umb_pktstate, (s))
124 #define umb_activation(s)	umb_val2descr(umb_actstate, (s))
125 #define umb_error2str(e)	umb_val2descr(umb_error, (e))
126 #define umb_pin_type(t)		umb_val2descr(umb_pintype, (t))
127 #define umb_istate(s)		umb_val2descr(umb_istate, (s))
128 
129 int		 umb_match(struct device *, void *, void *);
130 void		 umb_attach(struct device *, struct device *, void *);
131 int		 umb_detach(struct device *, int);
132 void		 umb_ncm_setup(struct umb_softc *);
133 void		 umb_ncm_setup_format(struct umb_softc *);
134 int		 umb_alloc_xfers(struct umb_softc *);
135 void		 umb_free_xfers(struct umb_softc *);
136 int		 umb_alloc_bulkpipes(struct umb_softc *);
137 void		 umb_close_bulkpipes(struct umb_softc *);
138 int		 umb_ioctl(struct ifnet *, u_long, caddr_t);
139 int		 umb_output(struct ifnet *, struct mbuf *, struct sockaddr *,
140 		    struct rtentry *);
141 void		 umb_input(struct ifnet *, struct mbuf *);
142 void		 umb_start(struct ifnet *);
143 void		 umb_rtrequest(struct ifnet *, int, struct rtentry *);
144 void		 umb_watchdog(struct ifnet *);
145 void		 umb_statechg_timeout(void *);
146 
147 void		 umb_newstate(struct umb_softc *, enum umb_state, int);
148 void		 umb_state_task(void *);
149 void		 umb_up(struct umb_softc *);
150 void		 umb_down(struct umb_softc *, int);
151 
152 void		 umb_get_response_task(void *);
153 
154 void		 umb_decode_response(struct umb_softc *, void *, int);
155 void		 umb_handle_indicate_status_msg(struct umb_softc *, void *,
156 		    int);
157 void		 umb_handle_opendone_msg(struct umb_softc *, void *, int);
158 void		 umb_handle_closedone_msg(struct umb_softc *, void *, int);
159 int		 umb_decode_register_state(struct umb_softc *, void *, int);
160 int		 umb_decode_devices_caps(struct umb_softc *, void *, int);
161 int		 umb_decode_subscriber_status(struct umb_softc *, void *, int);
162 int		 umb_decode_radio_state(struct umb_softc *, void *, int);
163 int		 umb_decode_pin(struct umb_softc *, void *, int);
164 int		 umb_decode_packet_service(struct umb_softc *, void *, int);
165 int		 umb_decode_signal_state(struct umb_softc *, void *, int);
166 int		 umb_decode_connect_info(struct umb_softc *, void *, int);
167 void		 umb_clear_addr(struct umb_softc *);
168 int		 umb_add_inet_config(struct umb_softc *, struct in_addr, u_int,
169 		    struct in_addr);
170 int		 umb_add_inet6_config(struct umb_softc *, struct in6_addr *,
171 		    u_int, struct in6_addr *);
172 void		 umb_send_inet_proposal(struct umb_softc *, int);
173 int		 umb_decode_ip_configuration(struct umb_softc *, void *, int);
174 void		 umb_rx(struct umb_softc *);
175 void		 umb_rxeof(struct usbd_xfer *, void *, usbd_status);
176 int		 umb_encap(struct umb_softc *, int);
177 void		 umb_txeof(struct usbd_xfer *, void *, usbd_status);
178 void		 umb_decap(struct umb_softc *, struct usbd_xfer *);
179 
180 usbd_status	 umb_send_encap_command(struct umb_softc *, void *, int);
181 int		 umb_get_encap_response(struct umb_softc *, void *, int *);
182 void		 umb_ctrl_msg(struct umb_softc *, uint32_t, void *, int);
183 
184 void		 umb_open(struct umb_softc *);
185 void		 umb_close(struct umb_softc *);
186 
187 int		 umb_setpin(struct umb_softc *, int, int, void *, int, void *,
188 		    int);
189 void		 umb_setdataclass(struct umb_softc *);
190 void		 umb_radio(struct umb_softc *, int);
191 void		 umb_allocate_cid(struct umb_softc *);
192 void		 umb_send_fcc_auth(struct umb_softc *);
193 void		 umb_packet_service(struct umb_softc *, int);
194 void		 umb_connect(struct umb_softc *);
195 void		 umb_disconnect(struct umb_softc *);
196 void		 umb_send_connect(struct umb_softc *, int);
197 
198 void		 umb_qry_ipconfig(struct umb_softc *);
199 void		 umb_cmd(struct umb_softc *, int, int, void *, int);
200 void		 umb_cmd1(struct umb_softc *, int, int, void *, int, uint8_t *);
201 void		 umb_command_done(struct umb_softc *, void *, int);
202 void		 umb_decode_cid(struct umb_softc *, uint32_t, void *, int);
203 void		 umb_decode_qmi(struct umb_softc *, uint8_t *, int);
204 
205 void		 umb_intr(struct usbd_xfer *, void *, usbd_status);
206 
207 int		 umb_xfer_tout = USBD_DEFAULT_TIMEOUT;
208 
209 uint8_t		 umb_uuid_basic_connect[] = MBIM_UUID_BASIC_CONNECT;
210 uint8_t		 umb_uuid_context_internet[] = MBIM_UUID_CONTEXT_INTERNET;
211 uint8_t		 umb_uuid_qmi_mbim[] = MBIM_UUID_QMI_MBIM;
212 uint32_t	 umb_session_id = 0;
213 
214 struct cfdriver umb_cd = {
215 	NULL, "umb", DV_IFNET
216 };
217 
218 const struct cfattach umb_ca = {
219 	sizeof (struct umb_softc),
220 	umb_match,
221 	umb_attach,
222 	umb_detach,
223 	NULL,
224 };
225 
226 int umb_delay = 4000;
227 
228 struct umb_quirk {
229 	struct usb_devno	 dev;
230 	u_int32_t		 umb_flags;
231 	int			 umb_confno;
232 	int			 umb_match;
233 };
234 const struct umb_quirk umb_quirks[] = {
235 	{ { USB_VENDOR_DELL, USB_PRODUCT_DELL_DW5821E },
236 	  0,
237 	  2,
238 	  UMATCH_VENDOR_PRODUCT
239 	},
240 
241 	{ { USB_VENDOR_QUECTEL, USB_PRODUCT_QUECTEL_EC25 },
242 	  0,
243 	  1,
244 	  UMATCH_VENDOR_PRODUCT
245 	},
246 
247 
248 	{ { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_ME906S },
249 	  UMBFLG_NDP_AT_END,
250 	  3,
251 	  UMATCH_VENDOR_PRODUCT
252 	},
253 
254 	{ { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM7455 },
255 	  UMBFLG_FCC_AUTH_REQUIRED,
256 	  0,
257 	  0
258 	},
259 
260 	{ { USB_VENDOR_SIMCOM, USB_PRODUCT_SIMCOM_SIM7600 },
261 	  0,
262 	  1,
263 	  UMATCH_VENDOR_PRODUCT
264 	},
265 };
266 
267 #define umb_lookup(vid, pid)		\
268 	((const struct umb_quirk *)usb_lookup(umb_quirks, vid, pid))
269 
270 uint8_t umb_qmi_alloc_cid[] = {
271 	0x01,
272 	0x0f, 0x00,		/* len */
273 	0x00,			/* QMUX flags */
274 	0x00,			/* service "ctl" */
275 	0x00,			/* CID */
276 	0x00,			/* QMI flags */
277 	0x01,			/* transaction */
278 	0x22, 0x00,		/* msg "Allocate CID" */
279 	0x04, 0x00,		/* TLV len */
280 	0x01, 0x01, 0x00, 0x02	/* TLV */
281 };
282 
283 uint8_t umb_qmi_fcc_auth[] = {
284 	0x01,
285 	0x0c, 0x00,		/* len */
286 	0x00,			/* QMUX flags */
287 	0x02,			/* service "dms" */
288 #define UMB_QMI_CID_OFFS	5
289 	0x00,			/* CID (filled in later) */
290 	0x00,			/* QMI flags */
291 	0x01, 0x00,		/* transaction */
292 	0x5f, 0x55,		/* msg "Send FCC Authentication" */
293 	0x00, 0x00		/* TLV len */
294 };
295 
296 int
297 umb_match(struct device *parent, void *match, void *aux)
298 {
299 	struct usb_attach_arg *uaa = aux;
300 	const struct umb_quirk *quirk;
301 	usb_interface_descriptor_t *id;
302 
303 	quirk = umb_lookup(uaa->vendor, uaa->product);
304 	if (quirk != NULL && quirk->umb_match)
305 		return (quirk->umb_match);
306 	if (!uaa->iface)
307 		return UMATCH_NONE;
308 	if ((id = usbd_get_interface_descriptor(uaa->iface)) == NULL)
309 		return UMATCH_NONE;
310 
311 	/*
312 	 * If this function implements NCM, check if alternate setting
313 	 * 1 implements MBIM.
314 	 */
315 	if (id->bInterfaceClass == UICLASS_CDC &&
316 	    id->bInterfaceSubClass ==
317 	    UISUBCLASS_NETWORK_CONTROL_MODEL)
318 		id = usbd_find_idesc(uaa->device->cdesc, uaa->iface->index, 1);
319 	if (id == NULL)
320 		return UMATCH_NONE;
321 
322 	if (id->bInterfaceClass == UICLASS_CDC &&
323 	    id->bInterfaceSubClass ==
324 	    UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL &&
325 	    id->bInterfaceProtocol == 0)
326 		return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
327 
328 	return UMATCH_NONE;
329 }
330 
331 void
332 umb_attach(struct device *parent, struct device *self, void *aux)
333 {
334 	struct umb_softc *sc = (struct umb_softc *)self;
335 	struct usb_attach_arg *uaa = aux;
336 	const struct umb_quirk *quirk;
337 	usbd_status status;
338 	struct usbd_desc_iter iter;
339 	const usb_descriptor_t *desc;
340 	int	 v;
341 	struct usb_cdc_union_descriptor *ud;
342 	struct mbim_descriptor *md;
343 	int	 i;
344 	int	 ctrl_ep;
345 	usb_interface_descriptor_t *id;
346 	usb_config_descriptor_t	*cd;
347 	usb_endpoint_descriptor_t *ed;
348 	usb_interface_assoc_descriptor_t *ad;
349 	int	 current_ifaceno = -1;
350 	int	 data_ifaceno = -1;
351 	int	 altnum;
352 	int	 s;
353 	struct ifnet *ifp;
354 
355 	sc->sc_udev = uaa->device;
356 	sc->sc_ctrl_ifaceno = uaa->ifaceno;
357 	ml_init(&sc->sc_tx_ml);
358 
359 	quirk = umb_lookup(uaa->vendor, uaa->product);
360 	if (quirk != NULL && quirk->umb_flags) {
361 		DPRINTF("%s: setting flags 0x%x from quirk\n", DEVNAM(sc),
362                     quirk->umb_flags);
363 		sc->sc_flags |= quirk->umb_flags;
364 	}
365 
366 	/*
367 	 * Normally, MBIM devices are detected by their interface class and
368 	 * subclass. But for some models that have multiple configurations, it
369 	 * is better to match by vendor and product id so that we can select
370 	 * the desired configuration ourselves, e.g. to override a class-based
371 	 * match to another driver.
372 	 */
373 	if (uaa->configno < 0) {
374 		if (quirk == NULL) {
375 			printf("%s: unknown configuration for vid/pid match\n",
376 			    DEVNAM(sc));
377 			goto fail;
378 		}
379 		uaa->configno = quirk->umb_confno;
380 		DPRINTF("%s: switching to config #%d\n", DEVNAM(sc),
381 		    uaa->configno);
382 		status = usbd_set_config_no(sc->sc_udev, uaa->configno, 1);
383 		if (status) {
384 			printf("%s: failed to switch to config #%d: %s\n",
385 			    DEVNAM(sc), uaa->configno, usbd_errstr(status));
386 			goto fail;
387 		}
388 		usbd_delay_ms(sc->sc_udev, 200);
389 
390 		/*
391 		 * Need to do some manual setup that usbd_probe_and_attach()
392 		 * would do for us otherwise.
393 		 */
394 		uaa->nifaces = uaa->device->cdesc->bNumInterfaces;
395 		for (i = 0; i < uaa->nifaces; i++) {
396 			if (usbd_iface_claimed(sc->sc_udev, i))
397 				continue;
398 			id = usbd_get_interface_descriptor(&uaa->device->ifaces[i]);
399 			if (id != NULL && id->bInterfaceClass == UICLASS_CDC &&
400 			    id->bInterfaceSubClass ==
401 			    UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL) {
402 				uaa->iface = &uaa->device->ifaces[i];
403 				uaa->ifaceno = uaa->iface->idesc->bInterfaceNumber;
404 				sc->sc_ctrl_ifaceno = uaa->ifaceno;
405 				break;
406 			}
407 		}
408 	}
409 
410 	/*
411 	 * Some MBIM hardware does not provide the mandatory CDC Union
412 	 * Descriptor, so we also look at matching Interface
413 	 * Association Descriptors to find out the MBIM Data Interface
414 	 * number.
415 	 */
416 	sc->sc_ver_maj = sc->sc_ver_min = -1;
417 	sc->sc_maxpktlen = MBIM_MAXSEGSZ_MINVAL;
418 	usbd_desc_iter_init(sc->sc_udev, &iter);
419 	while ((desc = usbd_desc_iter_next(&iter))) {
420 		if (desc->bDescriptorType == UDESC_IFACE_ASSOC) {
421 			ad = (usb_interface_assoc_descriptor_t *)desc;
422 			if (ad->bFirstInterface == uaa->ifaceno &&
423 			    ad->bInterfaceCount > 1)
424 				data_ifaceno = uaa->ifaceno + 1;
425 			continue;
426 		}
427 		if (desc->bDescriptorType == UDESC_INTERFACE) {
428 			id = (usb_interface_descriptor_t *)desc;
429 			current_ifaceno = id->bInterfaceNumber;
430 			continue;
431 		}
432 		if (current_ifaceno != uaa->ifaceno)
433 			continue;
434 		if (desc->bDescriptorType != UDESC_CS_INTERFACE)
435 			continue;
436 		switch (desc->bDescriptorSubtype) {
437 		case UDESCSUB_CDC_UNION:
438 			ud = (struct usb_cdc_union_descriptor *)desc;
439 			data_ifaceno = ud->bSlaveInterface[0];
440 			break;
441 		case UDESCSUB_MBIM:
442 			md = (struct mbim_descriptor *)desc;
443 			v = UGETW(md->bcdMBIMVersion);
444 			sc->sc_ver_maj = MBIM_VER_MAJOR(v);
445 			sc->sc_ver_min = MBIM_VER_MINOR(v);
446 			sc->sc_ctrl_len = UGETW(md->wMaxControlMessage);
447 			/* Never trust a USB device! Could try to exploit us */
448 			if (sc->sc_ctrl_len < MBIM_CTRLMSG_MINLEN ||
449 			    sc->sc_ctrl_len > MBIM_CTRLMSG_MAXLEN) {
450 				DPRINTF("%s: control message len %d out of "
451 				    "bounds [%d .. %d]\n", DEVNAM(sc),
452 				    sc->sc_ctrl_len, MBIM_CTRLMSG_MINLEN,
453 				    MBIM_CTRLMSG_MAXLEN);
454 				/* cont. anyway */
455 			}
456 			sc->sc_maxpktlen = UGETW(md->wMaxSegmentSize);
457 			DPRINTFN(2, "%s: ctrl_len=%d, maxpktlen=%d, cap=0x%x\n",
458 			    DEVNAM(sc), sc->sc_ctrl_len, sc->sc_maxpktlen,
459 			    md->bmNetworkCapabilities);
460 			break;
461 		default:
462 			break;
463 		}
464 	}
465 	if (sc->sc_ver_maj < 0) {
466 		printf("%s: missing MBIM descriptor\n", DEVNAM(sc));
467 		goto fail;
468 	}
469 	if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED)
470 		sc->sc_cid = -1;
471 
472 	for (i = 0; i < uaa->nifaces; i++) {
473 		if (usbd_iface_claimed(sc->sc_udev, i))
474 			continue;
475 		id = usbd_get_interface_descriptor(&sc->sc_udev->ifaces[i]);
476 		if (id != NULL && id->bInterfaceNumber == data_ifaceno) {
477 			sc->sc_data_iface = &sc->sc_udev->ifaces[i];
478 			usbd_claim_iface(sc->sc_udev, i);
479 		}
480 	}
481 	if (sc->sc_data_iface == NULL) {
482 		printf("%s: no data interface found\n", DEVNAM(sc));
483 		goto fail;
484 	}
485 
486 	/*
487 	 * If this is a combined NCM/MBIM function, switch to
488 	 * alternate setting one to enable MBIM.
489 	 */
490 	id = usbd_get_interface_descriptor(uaa->iface);
491 	if (id->bInterfaceClass == UICLASS_CDC &&
492 	    id->bInterfaceSubClass ==
493 	    UISUBCLASS_NETWORK_CONTROL_MODEL)
494 		usbd_set_interface(uaa->iface, 1);
495 
496 	id = usbd_get_interface_descriptor(uaa->iface);
497 	ctrl_ep = -1;
498 	for (i = 0; i < id->bNumEndpoints && ctrl_ep == -1; i++) {
499 		ed = usbd_interface2endpoint_descriptor(uaa->iface, i);
500 		if (ed == NULL)
501 			break;
502 		if (UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT &&
503 		    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
504 			ctrl_ep = ed->bEndpointAddress;
505 	}
506 	if (ctrl_ep == -1) {
507 		printf("%s: missing interrupt endpoint\n", DEVNAM(sc));
508 		goto fail;
509 	}
510 
511 	/*
512 	 * For the MBIM Data Interface, select the appropriate
513 	 * alternate setting by looking for a matching descriptor that
514 	 * has two endpoints.
515 	 */
516 	cd = usbd_get_config_descriptor(sc->sc_udev);
517 	altnum = usbd_get_no_alts(cd, data_ifaceno);
518 	for (i = 0; i < altnum; i++) {
519 		id = usbd_find_idesc(cd, sc->sc_data_iface->index, i);
520 		if (id == NULL)
521 			continue;
522 		if (id->bInterfaceClass == UICLASS_CDC_DATA &&
523 		    id->bInterfaceSubClass == UISUBCLASS_DATA &&
524 		    id->bInterfaceProtocol == UIPROTO_DATA_MBIM &&
525 		    id->bNumEndpoints == 2)
526 			break;
527 	}
528 	if (i == altnum || id == NULL) {
529 		printf("%s: missing alt setting for interface #%d\n",
530 		    DEVNAM(sc), data_ifaceno);
531 		goto fail;
532 	}
533 	status = usbd_set_interface(sc->sc_data_iface, i);
534 	if (status) {
535 		printf("%s: select alt setting %d for interface #%d "
536 		    "failed: %s\n", DEVNAM(sc), i, data_ifaceno,
537 		    usbd_errstr(status));
538 		goto fail;
539 	}
540 
541 	id = usbd_get_interface_descriptor(sc->sc_data_iface);
542 	sc->sc_rx_ep = sc->sc_tx_ep = -1;
543 	for (i = 0; i < id->bNumEndpoints; i++) {
544 		if ((ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface,
545 		    i)) == NULL)
546 			break;
547 		if (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
548 		    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
549 			sc->sc_rx_ep = ed->bEndpointAddress;
550 		else if (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
551 		    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
552 			sc->sc_tx_ep = ed->bEndpointAddress;
553 	}
554 	if (sc->sc_rx_ep == -1 || sc->sc_tx_ep == -1) {
555 		printf("%s: missing bulk endpoints\n", DEVNAM(sc));
556 		goto fail;
557 	}
558 
559 	DPRINTFN(2, "%s: ctrl-ifno#%d: ep-ctrl=%d, data-ifno#%d: ep-rx=%d, "
560 	    "ep-tx=%d\n", DEVNAM(sc), sc->sc_ctrl_ifaceno,
561 	    UE_GET_ADDR(ctrl_ep), data_ifaceno,
562 	    UE_GET_ADDR(sc->sc_rx_ep), UE_GET_ADDR(sc->sc_tx_ep));
563 
564 	usb_init_task(&sc->sc_umb_task, umb_state_task, sc,
565 	    USB_TASK_TYPE_GENERIC);
566 	usb_init_task(&sc->sc_get_response_task, umb_get_response_task, sc,
567 	    USB_TASK_TYPE_GENERIC);
568 	timeout_set(&sc->sc_statechg_timer, umb_statechg_timeout, sc);
569 
570 	if (usbd_open_pipe_intr(uaa->iface, ctrl_ep, USBD_SHORT_XFER_OK,
571 	    &sc->sc_ctrl_pipe, sc, &sc->sc_intr_msg, sizeof (sc->sc_intr_msg),
572 	    umb_intr, USBD_DEFAULT_INTERVAL)) {
573 		printf("%s: failed to open control pipe\n", DEVNAM(sc));
574 		goto fail;
575 	}
576 	sc->sc_resp_buf = malloc(sc->sc_ctrl_len, M_USBDEV, M_NOWAIT);
577 	if (sc->sc_resp_buf == NULL) {
578 		printf("%s: allocation of resp buffer failed\n", DEVNAM(sc));
579 		goto fail;
580 	}
581 	sc->sc_ctrl_msg = malloc(sc->sc_ctrl_len, M_USBDEV, M_NOWAIT);
582 	if (sc->sc_ctrl_msg == NULL) {
583 		printf("%s: allocation of ctrl msg buffer failed\n",
584 		    DEVNAM(sc));
585 		goto fail;
586 	}
587 
588 	sc->sc_info.regstate = MBIM_REGSTATE_UNKNOWN;
589 	sc->sc_info.pin_attempts_left = UMB_VALUE_UNKNOWN;
590 	sc->sc_info.rssi = UMB_VALUE_UNKNOWN;
591 	sc->sc_info.ber = UMB_VALUE_UNKNOWN;
592 
593 	/* Default to 16 bit NTB format. */
594 	sc->sc_ncm_format = NCM_FORMAT_NTB16;
595 	umb_ncm_setup(sc);
596 	umb_ncm_setup_format(sc);
597 	if (sc->sc_ncm_supported_formats == 0)
598 		goto fail;
599 	DPRINTFN(2, "%s: rx/tx size %d/%d\n", DEVNAM(sc),
600 	    sc->sc_rx_bufsz, sc->sc_tx_bufsz);
601 
602 	s = splnet();
603 	ifp = GET_IFP(sc);
604 	ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_POINTOPOINT;
605 	ifp->if_ioctl = umb_ioctl;
606 	ifp->if_start = umb_start;
607 	ifp->if_rtrequest = umb_rtrequest;
608 
609 	ifp->if_watchdog = umb_watchdog;
610 	strlcpy(ifp->if_xname, DEVNAM(sc), IFNAMSIZ);
611 	ifp->if_link_state = LINK_STATE_DOWN;
612 
613 	ifp->if_type = IFT_MBIM;
614 	ifp->if_priority = IF_WWAN_DEFAULT_PRIORITY;
615 	ifp->if_addrlen = 0;
616 	ifp->if_hdrlen = sizeof (struct ncm_header16) +
617 	    sizeof (struct ncm_pointer16);
618 	ifp->if_mtu = 1500;		/* use a common default */
619 	ifp->if_hardmtu = sc->sc_maxpktlen;
620 	ifp->if_input = umb_input;
621 	ifp->if_output = umb_output;
622 	if_attach(ifp);
623 	if_alloc_sadl(ifp);
624 	ifp->if_softc = sc;
625 #if NBPFILTER > 0
626 	bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t));
627 #endif
628 	/*
629 	 * Open the device now so that we are able to query device information.
630 	 * XXX maybe close when done?
631 	 */
632 	umb_open(sc);
633 	splx(s);
634 
635 	DPRINTF("%s: vers %d.%d\n", DEVNAM(sc), sc->sc_ver_maj, sc->sc_ver_min);
636 	return;
637 
638 fail:
639 	usbd_deactivate(sc->sc_udev);
640 	return;
641 }
642 
643 int
644 umb_detach(struct device *self, int flags)
645 {
646 	struct umb_softc *sc = (struct umb_softc *)self;
647 	struct ifnet *ifp = GET_IFP(sc);
648 	int	 s;
649 
650 	s = splnet();
651 	if (ifp->if_flags & IFF_RUNNING)
652 		umb_down(sc, 1);
653 	umb_close(sc);
654 
655 	usb_rem_wait_task(sc->sc_udev, &sc->sc_get_response_task);
656 	if (timeout_initialized(&sc->sc_statechg_timer))
657 		timeout_del(&sc->sc_statechg_timer);
658 	sc->sc_nresp = 0;
659 	usb_rem_wait_task(sc->sc_udev, &sc->sc_umb_task);
660 	if (sc->sc_ctrl_pipe) {
661 		usbd_close_pipe(sc->sc_ctrl_pipe);
662 		sc->sc_ctrl_pipe = NULL;
663 	}
664 	if (sc->sc_ctrl_msg) {
665 		free(sc->sc_ctrl_msg, M_USBDEV, sc->sc_ctrl_len);
666 		sc->sc_ctrl_msg = NULL;
667 	}
668 	if (sc->sc_resp_buf) {
669 		free(sc->sc_resp_buf, M_USBDEV, sc->sc_ctrl_len);
670 		sc->sc_resp_buf = NULL;
671 	}
672 	if (ifp->if_softc != NULL) {
673 		if_detach(ifp);
674 	}
675 
676 	splx(s);
677 	return 0;
678 }
679 
680 void
681 umb_ncm_setup(struct umb_softc *sc)
682 {
683 	usb_device_request_t req;
684 	struct ncm_ntb_parameters np;
685 
686 	/* Query NTB transfer sizes */
687 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
688 	req.bRequest = NCM_GET_NTB_PARAMETERS;
689 	USETW(req.wValue, 0);
690 	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
691 	USETW(req.wLength, sizeof (np));
692 	if (usbd_do_request(sc->sc_udev, &req, &np) == USBD_NORMAL_COMPLETION &&
693 	    UGETW(np.wLength) == sizeof (np)) {
694 		sc->sc_rx_bufsz = UGETDW(np.dwNtbInMaxSize);
695 		sc->sc_tx_bufsz = UGETDW(np.dwNtbOutMaxSize);
696 		sc->sc_maxdgram = UGETW(np.wNtbOutMaxDatagrams);
697 		sc->sc_align = UGETW(np.wNdpOutAlignment);
698 		sc->sc_ndp_div = UGETW(np.wNdpOutDivisor);
699 		sc->sc_ndp_remainder = UGETW(np.wNdpOutPayloadRemainder);
700 		/* Validate values */
701 		if (!powerof2(sc->sc_align) || sc->sc_align == 0 ||
702 		    sc->sc_align >= sc->sc_tx_bufsz)
703 			sc->sc_align = sizeof (uint32_t);
704 		if (!powerof2(sc->sc_ndp_div) || sc->sc_ndp_div == 0 ||
705 		    sc->sc_ndp_div >= sc->sc_tx_bufsz)
706 			sc->sc_ndp_div = sizeof (uint32_t);
707 		if (sc->sc_ndp_remainder >= sc->sc_ndp_div)
708 			sc->sc_ndp_remainder = 0;
709 		DPRINTF("%s: NCM align=%d div=%d rem=%d\n", DEVNAM(sc),
710 		    sc->sc_align, sc->sc_ndp_div, sc->sc_ndp_remainder);
711 		sc->sc_ncm_supported_formats = UGETW(np.bmNtbFormatsSupported);
712 	} else {
713 		sc->sc_rx_bufsz = sc->sc_tx_bufsz = 8 * 1024;
714 		sc->sc_maxdgram = 0;
715 		sc->sc_align = sc->sc_ndp_div = sizeof (uint32_t);
716 		sc->sc_ndp_remainder = 0;
717 		DPRINTF("%s: align=default div=default rem=default\n",
718 		    DEVNAM(sc));
719 		sc->sc_ncm_supported_formats = NCM_FORMAT_NTB16_MASK;
720 	}
721 }
722 
723 void
724 umb_ncm_setup_format(struct umb_softc *sc)
725 {
726 	usb_device_request_t req;
727 	uWord wFmt;
728 	uint16_t fmt;
729 
730 	assertwaitok();
731 	if (sc->sc_ncm_supported_formats == 0)
732 		goto fail;
733 
734 	/* NCM_GET_NTB_FORMAT is not allowed for 16-bit only devices. */
735 	if (sc->sc_ncm_supported_formats == NCM_FORMAT_NTB16_MASK) {
736 		DPRINTF("%s: Only NTB16 format supported.\n", DEVNAM(sc));
737 		sc->sc_ncm_format = NCM_FORMAT_NTB16;
738 		return;
739 	}
740 
741 	/* Query NTB FORMAT (16 vs. 32 bit) */
742 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
743 	req.bRequest = NCM_GET_NTB_FORMAT;
744 	USETW(req.wValue, 0);
745 	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
746 	USETW(req.wLength, sizeof (wFmt));
747 	if (usbd_do_request(sc->sc_udev, &req, wFmt) != USBD_NORMAL_COMPLETION)
748 		goto fail;
749 	fmt = UGETW(wFmt);
750 	if ((sc->sc_ncm_supported_formats & (1UL << fmt)) == 0)
751 		goto fail;
752 	if (fmt != NCM_FORMAT_NTB16 && fmt != NCM_FORMAT_NTB32)
753 		goto fail;
754 	sc->sc_ncm_format = fmt;
755 
756 	DPRINTF("%s: Using NCM format %d, supported=0x%x\n",
757 	    DEVNAM(sc), sc->sc_ncm_format, sc->sc_ncm_supported_formats);
758 	return;
759 
760 fail:
761 	DPRINTF("%s: Cannot setup NCM format\n", DEVNAM(sc));
762 	sc->sc_ncm_supported_formats = 0;
763 }
764 
765 int
766 umb_alloc_xfers(struct umb_softc *sc)
767 {
768 	if (!sc->sc_rx_xfer) {
769 		if ((sc->sc_rx_xfer = usbd_alloc_xfer(sc->sc_udev)) != NULL)
770 			sc->sc_rx_buf = usbd_alloc_buffer(sc->sc_rx_xfer,
771 			    sc->sc_rx_bufsz);
772 	}
773 	if (!sc->sc_tx_xfer) {
774 		if ((sc->sc_tx_xfer = usbd_alloc_xfer(sc->sc_udev)) != NULL)
775 			sc->sc_tx_buf = usbd_alloc_buffer(sc->sc_tx_xfer,
776 			    sc->sc_tx_bufsz);
777 	}
778 	return (sc->sc_rx_buf && sc->sc_tx_buf) ? 1 : 0;
779 }
780 
781 void
782 umb_free_xfers(struct umb_softc *sc)
783 {
784 	if (sc->sc_rx_xfer) {
785 		/* implicit usbd_free_buffer() */
786 		usbd_free_xfer(sc->sc_rx_xfer);
787 		sc->sc_rx_xfer = NULL;
788 		sc->sc_rx_buf = NULL;
789 	}
790 	if (sc->sc_tx_xfer) {
791 		usbd_free_xfer(sc->sc_tx_xfer);
792 		sc->sc_tx_xfer = NULL;
793 		sc->sc_tx_buf = NULL;
794 	}
795 	ml_purge(&sc->sc_tx_ml);
796 }
797 
798 int
799 umb_alloc_bulkpipes(struct umb_softc *sc)
800 {
801 	struct ifnet *ifp = GET_IFP(sc);
802 
803 	if (!(ifp->if_flags & IFF_RUNNING)) {
804 		if (usbd_open_pipe(sc->sc_data_iface, sc->sc_rx_ep,
805 		    USBD_EXCLUSIVE_USE, &sc->sc_rx_pipe))
806 			return 0;
807 		if (usbd_open_pipe(sc->sc_data_iface, sc->sc_tx_ep,
808 		    USBD_EXCLUSIVE_USE, &sc->sc_tx_pipe))
809 			return 0;
810 
811 		ifp->if_flags |= IFF_RUNNING;
812 		ifq_clr_oactive(&ifp->if_snd);
813 		umb_rx(sc);
814 	}
815 	return 1;
816 }
817 
818 void
819 umb_close_bulkpipes(struct umb_softc *sc)
820 {
821 	struct ifnet *ifp = GET_IFP(sc);
822 
823 	ifp->if_flags &= ~IFF_RUNNING;
824 	ifq_clr_oactive(&ifp->if_snd);
825 	ifp->if_timer = 0;
826 	if (sc->sc_rx_pipe) {
827 		usbd_close_pipe(sc->sc_rx_pipe);
828 		sc->sc_rx_pipe = NULL;
829 	}
830 	if (sc->sc_tx_pipe) {
831 		usbd_close_pipe(sc->sc_tx_pipe);
832 		sc->sc_tx_pipe = NULL;
833 	}
834 }
835 
836 int
837 umb_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
838 {
839 	struct proc *p = curproc;
840 	struct umb_softc *sc = ifp->if_softc;
841 	struct ifreq *ifr = (struct ifreq *)data;
842 	int	 s, error = 0;
843 	struct umb_parameter mp;
844 
845 	if (usbd_is_dying(sc->sc_udev))
846 		return ENXIO;
847 
848 	s = splnet();
849 	switch (cmd) {
850 	case SIOCSIFFLAGS:
851 		usb_add_task(sc->sc_udev, &sc->sc_umb_task);
852 		break;
853 	case SIOCGUMBINFO:
854 		error = copyout(&sc->sc_info, ifr->ifr_data,
855 		    sizeof (sc->sc_info));
856 		break;
857 	case SIOCSUMBPARAM:
858 		if ((error = suser(p)) != 0)
859 			break;
860 		if ((error = copyin(ifr->ifr_data, &mp, sizeof (mp))) != 0)
861 			break;
862 
863 		if ((error = umb_setpin(sc, mp.op, mp.is_puk, mp.pin, mp.pinlen,
864 		    mp.newpin, mp.newpinlen)) != 0)
865 			break;
866 
867 		if (mp.apnlen < 0 || mp.apnlen > sizeof (sc->sc_info.apn)) {
868 			error = EINVAL;
869 			break;
870 		}
871 		sc->sc_roaming = mp.roaming ? 1 : 0;
872 		memset(sc->sc_info.apn, 0, sizeof (sc->sc_info.apn));
873 		memcpy(sc->sc_info.apn, mp.apn, mp.apnlen);
874 		sc->sc_info.apnlen = mp.apnlen;
875 		sc->sc_info.preferredclasses = mp.preferredclasses;
876 		umb_setdataclass(sc);
877 		break;
878 	case SIOCGUMBPARAM:
879 		memset(&mp, 0, sizeof (mp));
880 		memcpy(mp.apn, sc->sc_info.apn, sc->sc_info.apnlen);
881 		mp.apnlen = sc->sc_info.apnlen;
882 		mp.roaming = sc->sc_roaming;
883 		mp.preferredclasses = sc->sc_info.preferredclasses;
884 		error = copyout(&mp, ifr->ifr_data, sizeof (mp));
885 		break;
886 	case SIOCSIFMTU:
887 		/* Does this include the NCM headers and tail? */
888 		if (ifr->ifr_mtu > ifp->if_hardmtu) {
889 			error = EINVAL;
890 			break;
891 		}
892 		ifp->if_mtu = ifr->ifr_mtu;
893 		break;
894 	case SIOCSIFADDR:
895 	case SIOCAIFADDR:
896 	case SIOCSIFDSTADDR:
897 	case SIOCADDMULTI:
898 	case SIOCDELMULTI:
899 		break;
900 	default:
901 		error = ENOTTY;
902 		break;
903 	}
904 	splx(s);
905 	return error;
906 }
907 
908 int
909 umb_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
910     struct rtentry *rtp)
911 {
912 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
913 		m_freem(m);
914 		return ENETDOWN;
915 	}
916 	m->m_pkthdr.ph_family = dst->sa_family;
917 	return if_enqueue(ifp, m);
918 }
919 
920 void
921 umb_input(struct ifnet *ifp, struct mbuf *m)
922 {
923 	uint32_t af;
924 
925 	if ((ifp->if_flags & IFF_UP) == 0) {
926 		m_freem(m);
927 		return;
928 	}
929 	if (m->m_pkthdr.len < sizeof (struct ip) + sizeof(af)) {
930 		ifp->if_ierrors++;
931 		DPRINTFN(4, "%s: dropping short packet (len %d)\n", __func__,
932 		    m->m_pkthdr.len);
933 		m_freem(m);
934 		return;
935 	}
936 	m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
937 
938 	/* pop off DLT_LOOP header, no longer needed */
939 	af = *mtod(m, uint32_t *);
940 	m_adj(m, sizeof (af));
941 	af = ntohl(af);
942 
943 	ifp->if_ibytes += m->m_pkthdr.len;
944 	switch (af) {
945 	case AF_INET:
946 		ipv4_input(ifp, m);
947 		return;
948 #ifdef INET6
949 	case AF_INET6:
950 		ipv6_input(ifp, m);
951 		return;
952 #endif /* INET6 */
953 	default:
954 		ifp->if_ierrors++;
955 		DPRINTFN(4, "%s: dropping packet with bad IP version (af %d)\n",
956 		    __func__, af);
957 		m_freem(m);
958 		return;
959 	}
960 }
961 
962 static inline int
963 umb_align(size_t bufsz, int offs, int alignment, int remainder)
964 {
965 	size_t	 m = alignment - 1;
966 	int	 align;
967 
968 	align = (((size_t)offs + m) & ~m) - alignment + remainder;
969 	if (align < offs)
970 		align += alignment;
971 	if (align > bufsz)
972 		align = bufsz;
973 	return align - offs;
974 }
975 
976 static inline int
977 umb_padding(void *buf, size_t bufsz, int offs, int alignment, int remainder)
978 {
979 	int	 nb;
980 
981 	nb = umb_align(bufsz, offs, alignment, remainder);
982 	if (nb > 0)
983 		memset(buf + offs, 0, nb);
984 	return nb;
985 }
986 
987 void
988 umb_start(struct ifnet *ifp)
989 {
990 	struct umb_softc *sc = ifp->if_softc;
991 	struct mbuf *m = NULL;
992 	int	 ndgram = 0;
993 	int	 offs, len, mlen;
994 	int	 maxoverhead;
995 
996 	if (usbd_is_dying(sc->sc_udev) ||
997 	    !(ifp->if_flags & IFF_RUNNING) ||
998 	    ifq_is_oactive(&ifp->if_snd))
999 		return;
1000 
1001 	KASSERT(ml_empty(&sc->sc_tx_ml));
1002 
1003 	switch (sc->sc_ncm_format) {
1004 	case NCM_FORMAT_NTB16:
1005 		offs = sizeof (struct ncm_header16);
1006 		offs += umb_align(sc->sc_tx_bufsz, offs, sc->sc_align, 0);
1007 		offs += sizeof (struct ncm_pointer16);
1008 		maxoverhead = sizeof (struct ncm_pointer16_dgram);
1009 		break;
1010 	case NCM_FORMAT_NTB32:
1011 		offs = sizeof (struct ncm_header32);
1012 		offs += umb_align(sc->sc_tx_bufsz, offs, sc->sc_align, 0);
1013 		offs += sizeof (struct ncm_pointer32);
1014 		maxoverhead = sizeof (struct ncm_pointer32_dgram);
1015 		break;
1016 	}
1017 
1018 	/*
1019 	 * Overhead for per packet alignment plus packet pointer. Note
1020 	 * that 'struct ncm_pointer{16,32}' already includes space for
1021 	 * the terminating zero pointer.
1022 	 */
1023 	maxoverhead += sc->sc_ndp_div - 1;
1024 
1025 	len = 0;
1026 	while (1) {
1027 		m = ifq_deq_begin(&ifp->if_snd);
1028 		if (m == NULL)
1029 			break;
1030 
1031 		/*
1032 		 * Check if mbuf plus required NCM pointer still fits into
1033 		 * xfer buffers. Assume maximal padding.
1034 		 */
1035 		mlen = maxoverhead +  m->m_pkthdr.len;
1036 		if ((sc->sc_maxdgram != 0 && ndgram >= sc->sc_maxdgram) ||
1037 		    (offs + len + mlen > sc->sc_tx_bufsz)) {
1038 			ifq_deq_rollback(&ifp->if_snd, m);
1039 			break;
1040 		}
1041 		ifq_deq_commit(&ifp->if_snd, m);
1042 
1043 		ndgram++;
1044 		len += mlen;
1045 		ml_enqueue(&sc->sc_tx_ml, m);
1046 
1047 #if NBPFILTER > 0
1048 		if (ifp->if_bpf)
1049 			bpf_mtap_af(ifp->if_bpf, m->m_pkthdr.ph_family, m,
1050 			    BPF_DIRECTION_OUT);
1051 #endif
1052 	}
1053 	if (ml_empty(&sc->sc_tx_ml))
1054 		return;
1055 	if (umb_encap(sc, ndgram)) {
1056 		ifq_set_oactive(&ifp->if_snd);
1057 		ifp->if_timer = (2 * umb_xfer_tout) / 1000;
1058 	}
1059 }
1060 
1061 void
1062 umb_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
1063 {
1064 	struct umb_softc *sc = ifp->if_softc;
1065 
1066 	if (req == RTM_PROPOSAL) {
1067 		KERNEL_LOCK();
1068 		umb_send_inet_proposal(sc, AF_INET);
1069 #ifdef INET6
1070 		umb_send_inet_proposal(sc, AF_INET6);
1071 #endif
1072 		KERNEL_UNLOCK();
1073 		return;
1074 	}
1075 
1076 	p2p_rtrequest(ifp, req, rt);
1077 }
1078 
1079 
1080 void
1081 umb_watchdog(struct ifnet *ifp)
1082 {
1083 	struct umb_softc *sc = ifp->if_softc;
1084 
1085 	if (usbd_is_dying(sc->sc_udev))
1086 		return;
1087 
1088 	ifp->if_oerrors++;
1089 	printf("%s: watchdog timeout\n", DEVNAM(sc));
1090 	usbd_abort_pipe(sc->sc_tx_pipe);
1091 	return;
1092 }
1093 
1094 void
1095 umb_statechg_timeout(void *arg)
1096 {
1097 	struct umb_softc *sc = arg;
1098 	struct ifnet *ifp = GET_IFP(sc);
1099 
1100 	if (sc->sc_info.regstate != MBIM_REGSTATE_ROAMING || sc->sc_roaming)
1101 		if (ifp->if_flags & IFF_DEBUG)
1102 			log(LOG_DEBUG, "%s: state change timeout\n",
1103 			    DEVNAM(sc));
1104 	usb_add_task(sc->sc_udev, &sc->sc_umb_task);
1105 }
1106 
1107 void
1108 umb_newstate(struct umb_softc *sc, enum umb_state newstate, int flags)
1109 {
1110 	struct ifnet *ifp = GET_IFP(sc);
1111 
1112 	if (newstate == sc->sc_state)
1113 		return;
1114 	if (((flags & UMB_NS_DONT_DROP) && newstate < sc->sc_state) ||
1115 	    ((flags & UMB_NS_DONT_RAISE) && newstate > sc->sc_state))
1116 		return;
1117 	if (ifp->if_flags & IFF_DEBUG)
1118 		log(LOG_DEBUG, "%s: state going %s from '%s' to '%s'\n",
1119 		    DEVNAM(sc), newstate > sc->sc_state ? "up" : "down",
1120 		    umb_istate(sc->sc_state), umb_istate(newstate));
1121 	sc->sc_state = newstate;
1122 	usb_add_task(sc->sc_udev, &sc->sc_umb_task);
1123 }
1124 
1125 void
1126 umb_state_task(void *arg)
1127 {
1128 	struct umb_softc *sc = arg;
1129 	struct ifnet *ifp = GET_IFP(sc);
1130 	int	 s;
1131 	int	 state;
1132 
1133 	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
1134 		/*
1135 		 * Query the registration state until we're with the home
1136 		 * network again.
1137 		 */
1138 		umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY, NULL, 0);
1139 		return;
1140 	}
1141 
1142 	s = splnet();
1143 	if (ifp->if_flags & IFF_UP)
1144 		umb_up(sc);
1145 	else
1146 		umb_down(sc, 0);
1147 
1148 	state = sc->sc_state == UMB_S_UP ? LINK_STATE_UP : LINK_STATE_DOWN;
1149 	if (ifp->if_link_state != state) {
1150 		if (ifp->if_flags & IFF_DEBUG)
1151 			log(LOG_DEBUG, "%s: link state changed from %s to %s\n",
1152 			    DEVNAM(sc),
1153 			    LINK_STATE_IS_UP(ifp->if_link_state)
1154 			    ? "up" : "down",
1155 			    LINK_STATE_IS_UP(state) ? "up" : "down");
1156 		ifp->if_link_state = state;
1157 		if_link_state_change(ifp);
1158 	}
1159 	splx(s);
1160 }
1161 
1162 void
1163 umb_up(struct umb_softc *sc)
1164 {
1165 	splassert(IPL_NET);
1166 
1167 	switch (sc->sc_state) {
1168 	case UMB_S_DOWN:
1169 		DPRINTF("%s: init: opening ...\n", DEVNAM(sc));
1170 		umb_open(sc);
1171 		break;
1172 	case UMB_S_OPEN:
1173 		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED) {
1174 			if (sc->sc_cid == -1) {
1175 				DPRINTF("%s: init: allocating CID ...\n",
1176 				    DEVNAM(sc));
1177 				umb_allocate_cid(sc);
1178 				break;
1179 			} else
1180 				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
1181 		} else {
1182 			DPRINTF("%s: init: turning radio on ...\n", DEVNAM(sc));
1183 			umb_radio(sc, 1);
1184 			break;
1185 		}
1186 		/*FALLTHROUGH*/
1187 	case UMB_S_CID:
1188 		DPRINTF("%s: init: sending FCC auth ...\n", DEVNAM(sc));
1189 		umb_send_fcc_auth(sc);
1190 		break;
1191 	case UMB_S_RADIO:
1192 		DPRINTF("%s: init: checking SIM state ...\n", DEVNAM(sc));
1193 		umb_cmd(sc, MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CMDOP_QRY,
1194 		    NULL, 0);
1195 		break;
1196 	case UMB_S_SIMREADY:
1197 		DPRINTF("%s: init: attaching ...\n", DEVNAM(sc));
1198 		umb_packet_service(sc, 1);
1199 		break;
1200 	case UMB_S_ATTACHED:
1201 		sc->sc_tx_seq = 0;
1202 		if (!umb_alloc_xfers(sc)) {
1203 			umb_free_xfers(sc);
1204 			printf("%s: allocation of xfers failed\n", DEVNAM(sc));
1205 			break;
1206 		}
1207 		DPRINTF("%s: init: connecting ...\n", DEVNAM(sc));
1208 		umb_connect(sc);
1209 		break;
1210 	case UMB_S_CONNECTED:
1211 		DPRINTF("%s: init: getting IP config ...\n", DEVNAM(sc));
1212 		umb_qry_ipconfig(sc);
1213 		break;
1214 	case UMB_S_UP:
1215 		DPRINTF("%s: init: reached state UP\n", DEVNAM(sc));
1216 		if (!umb_alloc_bulkpipes(sc)) {
1217 			printf("%s: opening bulk pipes failed\n", DEVNAM(sc));
1218 			umb_down(sc, 1);
1219 		}
1220 		break;
1221 	}
1222 	if (sc->sc_state < UMB_S_UP)
1223 		timeout_add_sec(&sc->sc_statechg_timer,
1224 		    UMB_STATE_CHANGE_TIMEOUT);
1225 	else
1226 		timeout_del(&sc->sc_statechg_timer);
1227 	return;
1228 }
1229 
1230 void
1231 umb_down(struct umb_softc *sc, int force)
1232 {
1233 	splassert(IPL_NET);
1234 
1235 	umb_close_bulkpipes(sc);
1236 	if (sc->sc_state < UMB_S_CONNECTED)
1237 		umb_free_xfers(sc);
1238 
1239 	switch (sc->sc_state) {
1240 	case UMB_S_UP:
1241 		umb_clear_addr(sc);
1242 		/*FALLTHROUGH*/
1243 	case UMB_S_CONNECTED:
1244 		DPRINTF("%s: stop: disconnecting ...\n", DEVNAM(sc));
1245 		umb_disconnect(sc);
1246 		if (!force)
1247 			break;
1248 		/*FALLTHROUGH*/
1249 	case UMB_S_ATTACHED:
1250 		DPRINTF("%s: stop: detaching ...\n", DEVNAM(sc));
1251 		umb_packet_service(sc, 0);
1252 		if (!force)
1253 			break;
1254 		/*FALLTHROUGH*/
1255 	case UMB_S_SIMREADY:
1256 	case UMB_S_RADIO:
1257 		DPRINTF("%s: stop: turning radio off ...\n", DEVNAM(sc));
1258 		umb_radio(sc, 0);
1259 		if (!force)
1260 			break;
1261 		/*FALLTHROUGH*/
1262 	case UMB_S_CID:
1263 	case UMB_S_OPEN:
1264 	case UMB_S_DOWN:
1265 		/* Do not close the device */
1266 		DPRINTF("%s: stop: reached state DOWN\n", DEVNAM(sc));
1267 		break;
1268 	}
1269 	if (force)
1270 		sc->sc_state = UMB_S_OPEN;
1271 
1272 	if (sc->sc_state > UMB_S_OPEN)
1273 		timeout_add_sec(&sc->sc_statechg_timer,
1274 		    UMB_STATE_CHANGE_TIMEOUT);
1275 	else
1276 		timeout_del(&sc->sc_statechg_timer);
1277 }
1278 
1279 void
1280 umb_get_response_task(void *arg)
1281 {
1282 	struct umb_softc *sc = arg;
1283 	int	 len;
1284 	int	 s;
1285 
1286 	/*
1287 	 * Function is required to send on RESPONSE_AVAILABLE notification for
1288 	 * each encapsulated response that is to be processed by the host.
1289 	 * But of course, we can receive multiple notifications before the
1290 	 * response task is run.
1291 	 */
1292 	s = splusb();
1293 	while (sc->sc_nresp > 0) {
1294 		--sc->sc_nresp;
1295 		len = sc->sc_ctrl_len;
1296 		if (umb_get_encap_response(sc, sc->sc_resp_buf, &len))
1297 			umb_decode_response(sc, sc->sc_resp_buf, len);
1298 	}
1299 	splx(s);
1300 }
1301 
1302 void
1303 umb_decode_response(struct umb_softc *sc, void *response, int len)
1304 {
1305 	struct mbim_msghdr *hdr = response;
1306 	struct mbim_fragmented_msg_hdr *fraghdr;
1307 	uint32_t type;
1308 	uint32_t tid;
1309 
1310 	DPRINTFN(3, "%s: got response: len %d\n", DEVNAM(sc), len);
1311 	DDUMPN(4, response, len);
1312 
1313 	if (len < sizeof (*hdr) || letoh32(hdr->len) != len) {
1314 		/*
1315 		 * We should probably cancel a transaction, but since the
1316 		 * message is too short, we cannot decode the transaction
1317 		 * id (tid) and hence don't know, whom to cancel. Must wait
1318 		 * for the timeout.
1319 		 */
1320 		DPRINTF("%s: received short response (len %d)\n",
1321 		    DEVNAM(sc), len);
1322 		return;
1323 	}
1324 
1325 	/*
1326 	 * XXX FIXME: if message is fragmented, store it until last frag
1327 	 *	is received and then re-assemble all fragments.
1328 	 */
1329 	type = letoh32(hdr->type);
1330 	tid = letoh32(hdr->tid);
1331 	switch (type) {
1332 	case MBIM_INDICATE_STATUS_MSG:
1333 	case MBIM_COMMAND_DONE:
1334 		fraghdr = response;
1335 		if (letoh32(fraghdr->frag.nfrag) != 1) {
1336 			DPRINTF("%s: discarding fragmented messages\n",
1337 			    DEVNAM(sc));
1338 			return;
1339 		}
1340 		break;
1341 	default:
1342 		break;
1343 	}
1344 
1345 	DPRINTF("%s: <- rcv %s (tid %u)\n", DEVNAM(sc), umb_request2str(type),
1346 	    tid);
1347 	switch (type) {
1348 	case MBIM_FUNCTION_ERROR_MSG:
1349 	case MBIM_HOST_ERROR_MSG:
1350 	{
1351 		struct mbim_f2h_hosterr *e;
1352 		int	 err;
1353 
1354 		if (len >= sizeof (*e)) {
1355 			e = response;
1356 			err = letoh32(e->err);
1357 
1358 			DPRINTF("%s: %s message, error %s (tid %u)\n",
1359 			    DEVNAM(sc), umb_request2str(type),
1360 			    umb_error2str(err), tid);
1361 			if (err == MBIM_ERROR_NOT_OPENED)
1362 				umb_newstate(sc, UMB_S_DOWN, 0);
1363 		}
1364 		break;
1365 	}
1366 	case MBIM_INDICATE_STATUS_MSG:
1367 		umb_handle_indicate_status_msg(sc, response, len);
1368 		break;
1369 	case MBIM_OPEN_DONE:
1370 		umb_handle_opendone_msg(sc, response, len);
1371 		break;
1372 	case MBIM_CLOSE_DONE:
1373 		umb_handle_closedone_msg(sc, response, len);
1374 		break;
1375 	case MBIM_COMMAND_DONE:
1376 		umb_command_done(sc, response, len);
1377 		break;
1378 	default:
1379 		DPRINTF("%s: discard message %s\n", DEVNAM(sc),
1380 		    umb_request2str(type));
1381 		break;
1382 	}
1383 }
1384 
1385 void
1386 umb_handle_indicate_status_msg(struct umb_softc *sc, void *data, int len)
1387 {
1388 	struct mbim_f2h_indicate_status *m = data;
1389 	uint32_t infolen;
1390 	uint32_t cid;
1391 
1392 	if (len < sizeof (*m)) {
1393 		DPRINTF("%s: discard short %s message\n", DEVNAM(sc),
1394 		    umb_request2str(letoh32(m->hdr.type)));
1395 		return;
1396 	}
1397 	if (memcmp(m->devid, umb_uuid_basic_connect, sizeof (m->devid))) {
1398 		DPRINTF("%s: discard %s message for other UUID '%s'\n",
1399 		    DEVNAM(sc), umb_request2str(letoh32(m->hdr.type)),
1400 		    umb_uuid2str(m->devid));
1401 		return;
1402 	}
1403 	infolen = letoh32(m->infolen);
1404 	if (len < sizeof (*m) + infolen) {
1405 		DPRINTF("%s: discard truncated %s message (want %d, got %d)\n",
1406 		    DEVNAM(sc), umb_request2str(letoh32(m->hdr.type)),
1407 		    (int)sizeof (*m) + infolen, len);
1408 		return;
1409 	}
1410 
1411 	cid = letoh32(m->cid);
1412 	DPRINTF("%s: indicate %s status\n", DEVNAM(sc), umb_cid2str(cid));
1413 	umb_decode_cid(sc, cid, m->info, infolen);
1414 }
1415 
1416 void
1417 umb_handle_opendone_msg(struct umb_softc *sc, void *data, int len)
1418 {
1419 	struct mbim_f2h_openclosedone *resp = data;
1420 	struct ifnet *ifp = GET_IFP(sc);
1421 	uint32_t status;
1422 
1423 	status = letoh32(resp->status);
1424 	if (status == MBIM_STATUS_SUCCESS) {
1425 		if (sc->sc_maxsessions == 0) {
1426 			umb_cmd(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_QRY, NULL,
1427 			    0);
1428 			umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_QRY, NULL, 0);
1429 			umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY,
1430 			    NULL, 0);
1431 		}
1432 		umb_newstate(sc, UMB_S_OPEN, UMB_NS_DONT_DROP);
1433 	} else if (ifp->if_flags & IFF_DEBUG)
1434 		log(LOG_ERR, "%s: open error: %s\n", DEVNAM(sc),
1435 		    umb_status2str(status));
1436 	return;
1437 }
1438 
1439 void
1440 umb_handle_closedone_msg(struct umb_softc *sc, void *data, int len)
1441 {
1442 	struct mbim_f2h_openclosedone *resp = data;
1443 	uint32_t status;
1444 
1445 	status = letoh32(resp->status);
1446 	if (status == MBIM_STATUS_SUCCESS)
1447 		umb_newstate(sc, UMB_S_DOWN, 0);
1448 	else
1449 		DPRINTF("%s: close error: %s\n", DEVNAM(sc),
1450 		    umb_status2str(status));
1451 	return;
1452 }
1453 
1454 static inline void
1455 umb_getinfobuf(void *in, int inlen, uint32_t offs, uint32_t sz,
1456     void *out, size_t outlen)
1457 {
1458 	offs = letoh32(offs);
1459 	sz = letoh32(sz);
1460 	if (inlen >= offs + sz) {
1461 		memset(out, 0, outlen);
1462 		memcpy(out, in + offs, MIN(sz, outlen));
1463 	}
1464 }
1465 
1466 static inline int
1467 umb_addstr(void *buf, size_t bufsz, int *offs, void *str, int slen,
1468     uint32_t *offsmember, uint32_t *sizemember)
1469 {
1470 	if (*offs + slen > bufsz)
1471 		return 0;
1472 
1473 	*sizemember = htole32((uint32_t)slen);
1474 	if (slen && str) {
1475 		*offsmember = htole32((uint32_t)*offs);
1476 		memcpy(buf + *offs, str, slen);
1477 		*offs += slen;
1478 		*offs += umb_padding(buf, bufsz, *offs, sizeof (uint32_t), 0);
1479 	} else
1480 		*offsmember = htole32(0);
1481 	return 1;
1482 }
1483 
1484 int
1485 umb_decode_register_state(struct umb_softc *sc, void *data, int len)
1486 {
1487 	struct mbim_cid_registration_state_info *rs = data;
1488 	struct ifnet *ifp = GET_IFP(sc);
1489 
1490 	if (len < sizeof (*rs))
1491 		return 0;
1492 	sc->sc_info.nwerror = letoh32(rs->nwerror);
1493 	sc->sc_info.regstate = letoh32(rs->regstate);
1494 	sc->sc_info.regmode = letoh32(rs->regmode);
1495 	sc->sc_info.cellclass = letoh32(rs->curcellclass);
1496 
1497 	umb_getinfobuf(data, len, rs->provname_offs, rs->provname_size,
1498 	    sc->sc_info.provider, sizeof (sc->sc_info.provider));
1499 	umb_getinfobuf(data, len, rs->provid_offs, rs->provid_size,
1500 	    sc->sc_info.providerid, sizeof (sc->sc_info.providerid));
1501 	umb_getinfobuf(data, len, rs->roamingtxt_offs, rs->roamingtxt_size,
1502 	    sc->sc_info.roamingtxt, sizeof (sc->sc_info.roamingtxt));
1503 
1504 	DPRINTFN(2, "%s: %s, availclass 0x%x, class 0x%x, regmode %d\n",
1505 	    DEVNAM(sc), umb_regstate(sc->sc_info.regstate),
1506 	    letoh32(rs->availclasses), sc->sc_info.cellclass,
1507 	    sc->sc_info.regmode);
1508 
1509 	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING &&
1510 	    !sc->sc_roaming &&
1511 	    sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED) {
1512 		if (ifp->if_flags & IFF_DEBUG)
1513 			log(LOG_INFO,
1514 			    "%s: disconnecting from roaming network\n",
1515 			    DEVNAM(sc));
1516 		umb_disconnect(sc);
1517 	}
1518 	return 1;
1519 }
1520 
1521 int
1522 umb_decode_devices_caps(struct umb_softc *sc, void *data, int len)
1523 {
1524 	struct mbim_cid_device_caps *dc = data;
1525 
1526 	if (len < sizeof (*dc))
1527 		return 0;
1528 	sc->sc_maxsessions = letoh32(dc->max_sessions);
1529 	sc->sc_info.supportedclasses = letoh32(dc->dataclass);
1530 	umb_getinfobuf(data, len, dc->devid_offs, dc->devid_size,
1531 	    sc->sc_info.devid, sizeof (sc->sc_info.devid));
1532 	umb_getinfobuf(data, len, dc->fwinfo_offs, dc->fwinfo_size,
1533 	    sc->sc_info.fwinfo, sizeof (sc->sc_info.fwinfo));
1534 	umb_getinfobuf(data, len, dc->hwinfo_offs, dc->hwinfo_size,
1535 	    sc->sc_info.hwinfo, sizeof (sc->sc_info.hwinfo));
1536 	DPRINTFN(2, "%s: max sessions %d, supported classes 0x%x\n",
1537 	    DEVNAM(sc), sc->sc_maxsessions, sc->sc_info.supportedclasses);
1538 	return 1;
1539 }
1540 
1541 int
1542 umb_decode_subscriber_status(struct umb_softc *sc, void *data, int len)
1543 {
1544 	struct mbim_cid_subscriber_ready_info *si = data;
1545 	struct ifnet *ifp = GET_IFP(sc);
1546 	int	npn;
1547 
1548 	if (len < sizeof (*si))
1549 		return 0;
1550 	sc->sc_info.sim_state = letoh32(si->ready);
1551 
1552 	umb_getinfobuf(data, len, si->sid_offs, si->sid_size,
1553 	    sc->sc_info.sid, sizeof (sc->sc_info.sid));
1554 	umb_getinfobuf(data, len, si->icc_offs, si->icc_size,
1555 	    sc->sc_info.iccid, sizeof (sc->sc_info.iccid));
1556 
1557 	npn = letoh32(si->no_pn);
1558 	if (npn > 0)
1559 		umb_getinfobuf(data, len, si->pn[0].offs, si->pn[0].size,
1560 		    sc->sc_info.pn, sizeof (sc->sc_info.pn));
1561 	else
1562 		memset(sc->sc_info.pn, 0, sizeof (sc->sc_info.pn));
1563 
1564 	if (sc->sc_info.sim_state == MBIM_SIMSTATE_LOCKED)
1565 		sc->sc_info.pin_state = UMB_PUK_REQUIRED;
1566 	if (ifp->if_flags & IFF_DEBUG)
1567 		log(LOG_INFO, "%s: SIM %s\n", DEVNAM(sc),
1568 		    umb_simstate(sc->sc_info.sim_state));
1569 	if (sc->sc_info.sim_state == MBIM_SIMSTATE_INITIALIZED)
1570 		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_DROP);
1571 	return 1;
1572 }
1573 
1574 int
1575 umb_decode_radio_state(struct umb_softc *sc, void *data, int len)
1576 {
1577 	struct mbim_cid_radio_state_info *rs = data;
1578 	struct ifnet *ifp = GET_IFP(sc);
1579 
1580 	if (len < sizeof (*rs))
1581 		return 0;
1582 
1583 	sc->sc_info.hw_radio_on =
1584 	    (letoh32(rs->hw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1585 	sc->sc_info.sw_radio_on =
1586 	    (letoh32(rs->sw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1587 	if (!sc->sc_info.hw_radio_on) {
1588 		printf("%s: radio is disabled by hardware switch\n",
1589 		    DEVNAM(sc));
1590 		/*
1591 		 * XXX do we need a time to poll the state of the rfkill switch
1592 		 *	or will the device send an unsolicited notification
1593 		 *	in case the state changes?
1594 		 */
1595 		umb_newstate(sc, UMB_S_OPEN, 0);
1596 	} else if (!sc->sc_info.sw_radio_on) {
1597 		if (ifp->if_flags & IFF_DEBUG)
1598 			log(LOG_INFO, "%s: radio is off\n", DEVNAM(sc));
1599 		umb_newstate(sc, UMB_S_OPEN, 0);
1600 	} else
1601 		umb_newstate(sc, UMB_S_RADIO, UMB_NS_DONT_DROP);
1602 	return 1;
1603 }
1604 
1605 int
1606 umb_decode_pin(struct umb_softc *sc, void *data, int len)
1607 {
1608 	struct mbim_cid_pin_info *pi = data;
1609 	struct ifnet *ifp = GET_IFP(sc);
1610 	uint32_t	attempts_left;
1611 
1612 	if (len < sizeof (*pi))
1613 		return 0;
1614 
1615 	attempts_left = letoh32(pi->remaining_attempts);
1616 	if (attempts_left != 0xffffffff)
1617 		sc->sc_info.pin_attempts_left = attempts_left;
1618 
1619 	switch (letoh32(pi->state)) {
1620 	case MBIM_PIN_STATE_UNLOCKED:
1621 		sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1622 		break;
1623 	case MBIM_PIN_STATE_LOCKED:
1624 		switch (letoh32(pi->type)) {
1625 		case MBIM_PIN_TYPE_PIN1:
1626 			sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1627 			break;
1628 		case MBIM_PIN_TYPE_PUK1:
1629 			sc->sc_info.pin_state = UMB_PUK_REQUIRED;
1630 			break;
1631 		case MBIM_PIN_TYPE_PIN2:
1632 		case MBIM_PIN_TYPE_PUK2:
1633 			/* Assume that PIN1 was accepted */
1634 			sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1635 			break;
1636 		}
1637 		break;
1638 	}
1639 	if (ifp->if_flags & IFF_DEBUG)
1640 		log(LOG_INFO, "%s: %s state %s (%d attempts left)\n",
1641 		    DEVNAM(sc), umb_pin_type(letoh32(pi->type)),
1642 		    (letoh32(pi->state) == MBIM_PIN_STATE_UNLOCKED) ?
1643 			"unlocked" : "locked",
1644 		    letoh32(pi->remaining_attempts));
1645 
1646 	/*
1647 	 * In case the PIN was set after IFF_UP, retrigger the state machine
1648 	 */
1649 	usb_add_task(sc->sc_udev, &sc->sc_umb_task);
1650 	return 1;
1651 }
1652 
1653 int
1654 umb_decode_packet_service(struct umb_softc *sc, void *data, int len)
1655 {
1656 	struct mbim_cid_packet_service_info *psi = data;
1657 	int	 state, highestclass;
1658 	uint64_t up_speed, down_speed;
1659 	struct ifnet *ifp = GET_IFP(sc);
1660 
1661 	if (len < sizeof (*psi))
1662 		return 0;
1663 
1664 	sc->sc_info.nwerror = letoh32(psi->nwerror);
1665 	state = letoh32(psi->state);
1666 	highestclass = letoh32(psi->highest_dataclass);
1667 	up_speed = letoh64(psi->uplink_speed);
1668 	down_speed = letoh64(psi->downlink_speed);
1669 	if (sc->sc_info.packetstate  != state ||
1670 	    sc->sc_info.uplink_speed != up_speed ||
1671 	    sc->sc_info.downlink_speed != down_speed) {
1672 		if (ifp->if_flags & IFF_DEBUG) {
1673 			log(LOG_INFO, "%s: packet service ", DEVNAM(sc));
1674 			if (sc->sc_info.packetstate  != state)
1675 				addlog("changed from %s to ",
1676 				    umb_packet_state(sc->sc_info.packetstate));
1677 			addlog("%s, class %s, speed: %llu up / %llu down\n",
1678 			    umb_packet_state(state),
1679 			    umb_dataclass(highestclass), up_speed, down_speed);
1680 		}
1681 	}
1682 	sc->sc_info.packetstate = state;
1683 	sc->sc_info.highestclass = highestclass;
1684 	sc->sc_info.uplink_speed = up_speed;
1685 	sc->sc_info.downlink_speed = down_speed;
1686 
1687 	if (sc->sc_info.regmode == MBIM_REGMODE_AUTOMATIC) {
1688 		/*
1689 		 * For devices using automatic registration mode, just proceed,
1690 		 * once registration has completed.
1691 		 */
1692 		if (ifp->if_flags & IFF_UP) {
1693 			switch (sc->sc_info.regstate) {
1694 			case MBIM_REGSTATE_HOME:
1695 			case MBIM_REGSTATE_ROAMING:
1696 			case MBIM_REGSTATE_PARTNER:
1697 				umb_newstate(sc, UMB_S_ATTACHED,
1698 				    UMB_NS_DONT_DROP);
1699 				break;
1700 			default:
1701 				break;
1702 			}
1703 		} else
1704 			umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1705 	} else switch (sc->sc_info.packetstate) {
1706 	case MBIM_PKTSERVICE_STATE_ATTACHED:
1707 		umb_newstate(sc, UMB_S_ATTACHED, UMB_NS_DONT_DROP);
1708 		break;
1709 	case MBIM_PKTSERVICE_STATE_DETACHED:
1710 		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1711 		break;
1712 	}
1713 	return 1;
1714 }
1715 
1716 int
1717 umb_decode_signal_state(struct umb_softc *sc, void *data, int len)
1718 {
1719 	struct mbim_cid_signal_state *ss = data;
1720 	struct ifnet *ifp = GET_IFP(sc);
1721 	int	 rssi;
1722 
1723 	if (len < sizeof (*ss))
1724 		return 0;
1725 
1726 	if (letoh32(ss->rssi) == 99)
1727 		rssi = UMB_VALUE_UNKNOWN;
1728 	else {
1729 		rssi = -113 + 2 * letoh32(ss->rssi);
1730 		if ((ifp->if_flags & IFF_DEBUG) && sc->sc_info.rssi != rssi &&
1731 		    sc->sc_state >= UMB_S_CONNECTED)
1732 			log(LOG_INFO, "%s: rssi %d dBm\n", DEVNAM(sc), rssi);
1733 	}
1734 	sc->sc_info.rssi = rssi;
1735 	sc->sc_info.ber = letoh32(ss->err_rate);
1736 	if (sc->sc_info.ber == -99)
1737 		sc->sc_info.ber = UMB_VALUE_UNKNOWN;
1738 	return 1;
1739 }
1740 
1741 int
1742 umb_decode_connect_info(struct umb_softc *sc, void *data, int len)
1743 {
1744 	struct mbim_cid_connect_info *ci = data;
1745 	struct ifnet *ifp = GET_IFP(sc);
1746 	int	 act;
1747 
1748 	if (len < sizeof (*ci))
1749 		return 0;
1750 
1751 	if (letoh32(ci->sessionid) != umb_session_id) {
1752 		DPRINTF("%s: discard connection info for session %u\n",
1753 		    DEVNAM(sc), letoh32(ci->sessionid));
1754 		return 1;
1755 	}
1756 	if (memcmp(ci->context, umb_uuid_context_internet,
1757 	    sizeof (ci->context))) {
1758 		DPRINTF("%s: discard connection info for other context\n",
1759 		    DEVNAM(sc));
1760 		return 1;
1761 	}
1762 	act = letoh32(ci->activation);
1763 	if (sc->sc_info.activation != act) {
1764 		if (ifp->if_flags & IFF_DEBUG)
1765 			log(LOG_INFO, "%s: connection %s\n", DEVNAM(sc),
1766 			    umb_activation(act));
1767 
1768 		sc->sc_info.activation = act;
1769 		sc->sc_info.nwerror = letoh32(ci->nwerror);
1770 
1771 		if (sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED)
1772 			umb_newstate(sc, UMB_S_CONNECTED, UMB_NS_DONT_DROP);
1773 		else if (sc->sc_info.activation ==
1774 		    MBIM_ACTIVATION_STATE_DEACTIVATED)
1775 			umb_newstate(sc, UMB_S_ATTACHED, 0);
1776 		/* else: other states are purely transitional */
1777 	}
1778 	return 1;
1779 }
1780 
1781 void
1782 umb_clear_addr(struct umb_softc *sc)
1783 {
1784 	struct ifnet *ifp = GET_IFP(sc);
1785 
1786 	memset(sc->sc_info.ipv4dns, 0, sizeof (sc->sc_info.ipv4dns));
1787 	memset(sc->sc_info.ipv6dns, 0, sizeof (sc->sc_info.ipv6dns));
1788 	umb_send_inet_proposal(sc, AF_INET);
1789 #ifdef INET6
1790 	umb_send_inet_proposal(sc, AF_INET6);
1791 #endif
1792 	NET_LOCK();
1793 	in_ifdetach(ifp);
1794 #ifdef INET6
1795 	in6_ifdetach(ifp);
1796 #endif
1797 	NET_UNLOCK();
1798 }
1799 
1800 int
1801 umb_add_inet_config(struct umb_softc *sc, struct in_addr ip, u_int prefixlen,
1802     struct in_addr gw)
1803 {
1804 	struct ifnet *ifp = GET_IFP(sc);
1805 	struct in_aliasreq ifra;
1806 	struct sockaddr_in *sin, default_sin;
1807 	struct rt_addrinfo info;
1808 	struct rtentry *rt;
1809 	int	 rv;
1810 
1811 	memset(&ifra, 0, sizeof (ifra));
1812 	sin = &ifra.ifra_addr;
1813 	sin->sin_family = AF_INET;
1814 	sin->sin_len = sizeof (*sin);
1815 	sin->sin_addr = ip;
1816 
1817 	sin = &ifra.ifra_dstaddr;
1818 	sin->sin_family = AF_INET;
1819 	sin->sin_len = sizeof (*sin);
1820 	sin->sin_addr = gw;
1821 
1822 	sin = &ifra.ifra_mask;
1823 	sin->sin_family = AF_INET;
1824 	sin->sin_len = sizeof (*sin);
1825 	in_len2mask(&sin->sin_addr, prefixlen);
1826 
1827 	rv = in_ioctl(SIOCAIFADDR, (caddr_t)&ifra, ifp, 1);
1828 	if (rv != 0) {
1829 		printf("%s: unable to set IPv4 address, error %d\n",
1830 		    DEVNAM(ifp->if_softc), rv);
1831 		return rv;
1832 	}
1833 
1834 	memset(&default_sin, 0, sizeof(default_sin));
1835 	default_sin.sin_family = AF_INET;
1836 	default_sin.sin_len = sizeof (default_sin);
1837 
1838 	memset(&info, 0, sizeof(info));
1839 	info.rti_flags = RTF_GATEWAY /* maybe | RTF_STATIC */;
1840 	info.rti_ifa = ifa_ifwithaddr(sintosa(&ifra.ifra_addr),
1841 	    ifp->if_rdomain);
1842 	info.rti_info[RTAX_DST] = sintosa(&default_sin);
1843 	info.rti_info[RTAX_NETMASK] = sintosa(&default_sin);
1844 	info.rti_info[RTAX_GATEWAY] = sintosa(&ifra.ifra_dstaddr);
1845 
1846 	NET_LOCK();
1847 	rv = rtrequest(RTM_ADD, &info, 0, &rt, ifp->if_rdomain);
1848 	NET_UNLOCK();
1849 	if (rv) {
1850 		printf("%s: unable to set IPv4 default route, "
1851 		    "error %d\n", DEVNAM(ifp->if_softc), rv);
1852 		rtm_miss(RTM_MISS, &info, 0, RTP_NONE, 0, rv,
1853 		    ifp->if_rdomain);
1854 	} else {
1855 		/* Inform listeners of the new route */
1856 		rtm_send(rt, RTM_ADD, rv, ifp->if_rdomain);
1857 		rtfree(rt);
1858 	}
1859 
1860 	if (ifp->if_flags & IFF_DEBUG) {
1861 		char str[3][INET_ADDRSTRLEN];
1862 		log(LOG_INFO, "%s: IPv4 addr %s, mask %s, gateway %s\n",
1863 		    DEVNAM(ifp->if_softc),
1864 		    sockaddr_ntop(sintosa(&ifra.ifra_addr), str[0],
1865 		    sizeof(str[0])),
1866 		    sockaddr_ntop(sintosa(&ifra.ifra_mask), str[1],
1867 		    sizeof(str[1])),
1868 		    sockaddr_ntop(sintosa(&ifra.ifra_dstaddr), str[2],
1869 		    sizeof(str[2])));
1870 	}
1871 	return 0;
1872 }
1873 
1874 #ifdef INET6
1875 int
1876 umb_add_inet6_config(struct umb_softc *sc, struct in6_addr *ip, u_int prefixlen,
1877     struct in6_addr *gw)
1878 {
1879 	struct ifnet *ifp = GET_IFP(sc);
1880 	struct in6_aliasreq ifra;
1881 	struct sockaddr_in6 *sin6, default_sin6;
1882 	struct rt_addrinfo info;
1883 	struct rtentry *rt;
1884 	int	 rv;
1885 
1886 	memset(&ifra, 0, sizeof (ifra));
1887 	sin6 = &ifra.ifra_addr;
1888 	sin6->sin6_family = AF_INET6;
1889 	sin6->sin6_len = sizeof (*sin6);
1890 	memcpy(&sin6->sin6_addr, ip, sizeof (sin6->sin6_addr));
1891 
1892 	sin6 = &ifra.ifra_dstaddr;
1893 	sin6->sin6_family = AF_INET6;
1894 	sin6->sin6_len = sizeof (*sin6);
1895 	memcpy(&sin6->sin6_addr, gw, sizeof (sin6->sin6_addr));
1896 
1897 	/* XXX: in6_update_ifa() accepts only 128 bits for P2P interfaces. */
1898 	prefixlen = 128;
1899 
1900 	sin6 = &ifra.ifra_prefixmask;
1901 	sin6->sin6_family = AF_INET6;
1902 	sin6->sin6_len = sizeof (*sin6);
1903 	in6_prefixlen2mask(&sin6->sin6_addr, prefixlen);
1904 
1905 	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
1906 	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
1907 
1908 	rv = in6_ioctl(SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, 1);
1909 	if (rv != 0) {
1910 		printf("%s: unable to set IPv6 address, error %d\n",
1911 		    DEVNAM(ifp->if_softc), rv);
1912 		return rv;
1913 	}
1914 
1915 	memset(&default_sin6, 0, sizeof(default_sin6));
1916 	default_sin6.sin6_family = AF_INET6;
1917 	default_sin6.sin6_len = sizeof (default_sin6);
1918 
1919 	memset(&info, 0, sizeof(info));
1920 	info.rti_flags = RTF_GATEWAY /* maybe | RTF_STATIC */;
1921 	info.rti_ifa = ifa_ifwithaddr(sin6tosa(&ifra.ifra_addr),
1922 	    ifp->if_rdomain);
1923 	info.rti_info[RTAX_DST] = sin6tosa(&default_sin6);
1924 	info.rti_info[RTAX_NETMASK] = sin6tosa(&default_sin6);
1925 	info.rti_info[RTAX_GATEWAY] = sin6tosa(&ifra.ifra_dstaddr);
1926 
1927 	NET_LOCK();
1928 	rv = rtrequest(RTM_ADD, &info, 0, &rt, ifp->if_rdomain);
1929 	NET_UNLOCK();
1930 	if (rv) {
1931 		printf("%s: unable to set IPv6 default route, "
1932 		    "error %d\n", DEVNAM(ifp->if_softc), rv);
1933 		rtm_miss(RTM_MISS, &info, 0, RTP_NONE, 0, rv,
1934 		    ifp->if_rdomain);
1935 	} else {
1936 		/* Inform listeners of the new route */
1937 		rtm_send(rt, RTM_ADD, rv, ifp->if_rdomain);
1938 		rtfree(rt);
1939 	}
1940 
1941 	if (ifp->if_flags & IFF_DEBUG) {
1942 		char str[3][INET6_ADDRSTRLEN];
1943 		log(LOG_INFO, "%s: IPv6 addr %s, mask %s, gateway %s\n",
1944 		    DEVNAM(ifp->if_softc),
1945 		    sockaddr_ntop(sin6tosa(&ifra.ifra_addr), str[0],
1946 		    sizeof(str[0])),
1947 		    sockaddr_ntop(sin6tosa(&ifra.ifra_prefixmask), str[1],
1948 		    sizeof(str[1])),
1949 		    sockaddr_ntop(sin6tosa(&ifra.ifra_dstaddr), str[2],
1950 		    sizeof(str[2])));
1951 	}
1952 	return 0;
1953 }
1954 #endif
1955 
1956 void
1957 umb_send_inet_proposal(struct umb_softc *sc, int af)
1958 {
1959 	struct ifnet *ifp = GET_IFP(sc);
1960 	struct sockaddr_rtdns rtdns;
1961 	struct rt_addrinfo info;
1962 	int i, flag = 0;
1963 	size_t sz = 0;
1964 
1965 	memset(&rtdns, 0, sizeof(rtdns));
1966 	memset(&info, 0, sizeof(info));
1967 
1968 	for (i = 0; i < UMB_MAX_DNSSRV; i++) {
1969 		if (af == AF_INET) {
1970 			sz = sizeof (sc->sc_info.ipv4dns[i]);
1971 			if (sc->sc_info.ipv4dns[i].s_addr == INADDR_ANY)
1972 				break;
1973 			memcpy(rtdns.sr_dns + i * sz, &sc->sc_info.ipv4dns[i],
1974 			    sz);
1975 			flag = RTF_UP;
1976 #ifdef INET6
1977 		} else if (af == AF_INET6) {
1978 			sz = sizeof (sc->sc_info.ipv6dns[i]);
1979 			if (IN6_ARE_ADDR_EQUAL(&sc->sc_info.ipv6dns[i],
1980 			    &in6addr_any))
1981 				break;
1982 			memcpy(rtdns.sr_dns + i * sz, &sc->sc_info.ipv6dns[i],
1983 			    sz);
1984 			flag = RTF_UP;
1985 #endif
1986 		}
1987 	}
1988 	rtdns.sr_family = af;
1989 	rtdns.sr_len = 2 + i * sz;
1990 	info.rti_info[RTAX_DNS] = srtdnstosa(&rtdns);
1991 
1992 	rtm_proposal(ifp, &info, flag, RTP_PROPOSAL_UMB);
1993 }
1994 
1995 int
1996 umb_decode_ip_configuration(struct umb_softc *sc, void *data, int len)
1997 {
1998 	struct mbim_cid_ip_configuration_info *ic = data;
1999 	struct ifnet *ifp = GET_IFP(sc);
2000 	int	 s;
2001 	uint32_t avail_v4;
2002 	uint32_t val;
2003 	int	 n, i;
2004 	int	 off;
2005 	struct mbim_cid_ipv4_element ipv4elem;
2006 	struct in_addr addr, gw;
2007 	int	 state = -1;
2008 	int	 rv;
2009 	int	 hasmtu = 0;
2010 #ifdef INET6
2011 	uint32_t avail_v6;
2012 	struct mbim_cid_ipv6_element ipv6elem;
2013 	struct in6_addr addr6, gw6;
2014 #endif
2015 
2016 	if (len < sizeof (*ic))
2017 		return 0;
2018 	if (letoh32(ic->sessionid) != umb_session_id) {
2019 		DPRINTF("%s: ignore IP configuration for session id %d\n",
2020 		    DEVNAM(sc), letoh32(ic->sessionid));
2021 		return 0;
2022 	}
2023 	s = splnet();
2024 
2025 	memset(sc->sc_info.ipv4dns, 0, sizeof (sc->sc_info.ipv4dns));
2026 	memset(sc->sc_info.ipv6dns, 0, sizeof (sc->sc_info.ipv6dns));
2027 
2028 	/*
2029 	 * IPv4 configuration
2030 	 */
2031 	avail_v4 = letoh32(ic->ipv4_available);
2032 	if ((avail_v4 & (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) ==
2033 	    (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) {
2034 		n = letoh32(ic->ipv4_naddr);
2035 		off = letoh32(ic->ipv4_addroffs);
2036 
2037 		if (n == 0 || off + sizeof (ipv4elem) > len)
2038 			goto tryv6;
2039 		if (n != 1 && ifp->if_flags & IFF_DEBUG)
2040 			log(LOG_INFO, "%s: more than one IPv4 addr: %d\n",
2041 			    DEVNAM(ifp->if_softc), n);
2042 
2043 		/* Only pick the first one */
2044 		memcpy(&ipv4elem, data + off, sizeof (ipv4elem));
2045 		ipv4elem.prefixlen = letoh32(ipv4elem.prefixlen);
2046 		addr.s_addr = ipv4elem.addr;
2047 
2048 		off = letoh32(ic->ipv4_gwoffs);
2049 		if (off + sizeof (gw) > len)
2050 			goto done;
2051 		memcpy(&gw, data + off, sizeof(gw));
2052 
2053 		rv = umb_add_inet_config(sc, addr, ipv4elem.prefixlen, gw);
2054 		if (rv == 0)
2055 			state = UMB_S_UP;
2056 
2057 	}
2058 
2059 	memset(sc->sc_info.ipv4dns, 0, sizeof (sc->sc_info.ipv4dns));
2060 	if (avail_v4 & MBIM_IPCONF_HAS_DNSINFO) {
2061 		n = letoh32(ic->ipv4_ndnssrv);
2062 		off = letoh32(ic->ipv4_dnssrvoffs);
2063 		i = 0;
2064 		while (n-- > 0) {
2065 			if (off + sizeof (addr) > len)
2066 				break;
2067 			memcpy(&addr, data + off, sizeof(addr));
2068 			if (i < UMB_MAX_DNSSRV)
2069 				sc->sc_info.ipv4dns[i++] = addr;
2070 			off += sizeof(addr);
2071 			if (ifp->if_flags & IFF_DEBUG) {
2072 				char str[INET_ADDRSTRLEN];
2073 				log(LOG_INFO, "%s: IPv4 nameserver %s\n",
2074 				    DEVNAM(ifp->if_softc), inet_ntop(AF_INET,
2075 				    &addr, str, sizeof(str)));
2076 			}
2077 		}
2078 		umb_send_inet_proposal(sc, AF_INET);
2079 	}
2080 	if ((avail_v4 & MBIM_IPCONF_HAS_MTUINFO)) {
2081 		val = letoh32(ic->ipv4_mtu);
2082 		if (ifp->if_hardmtu != val && val <= sc->sc_maxpktlen) {
2083 			hasmtu = 1;
2084 			ifp->if_hardmtu = val;
2085 			if (ifp->if_mtu > val)
2086 				ifp->if_mtu = val;
2087 		}
2088 	}
2089 
2090 tryv6:;
2091 #ifdef INET6
2092 	/*
2093 	 * IPv6 configuration
2094 	 */
2095 	avail_v6 = letoh32(ic->ipv6_available);
2096 	if (avail_v6 == 0) {
2097 		if (ifp->if_flags & IFF_DEBUG)
2098 			log(LOG_INFO, "%s: ISP or WWAN module offers no IPv6 "
2099 			    "support\n", DEVNAM(ifp->if_softc));
2100 		goto done;
2101 	}
2102 
2103 	if ((avail_v6 & (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) ==
2104 	    (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) {
2105 		n = letoh32(ic->ipv6_naddr);
2106 		off = letoh32(ic->ipv6_addroffs);
2107 
2108 		if (n == 0 || off + sizeof (ipv6elem) > len)
2109 			goto done;
2110 		if (n != 1 && ifp->if_flags & IFF_DEBUG)
2111 			log(LOG_INFO, "%s: more than one IPv6 addr: %d\n",
2112 			    DEVNAM(ifp->if_softc), n);
2113 
2114 		/* Only pick the first one */
2115 		memcpy(&ipv6elem, data + off, sizeof (ipv6elem));
2116 		memcpy(&addr6, ipv6elem.addr, sizeof (addr6));
2117 
2118 		off = letoh32(ic->ipv6_gwoffs);
2119 		if (off + sizeof (gw6) > len)
2120 			goto done;
2121 		memcpy(&gw6, data + off, sizeof (gw6));
2122 
2123 		rv = umb_add_inet6_config(sc, &addr6, ipv6elem.prefixlen, &gw6);
2124 		if (rv == 0)
2125 			state = UMB_S_UP;
2126 	}
2127 
2128 	if (avail_v6 & MBIM_IPCONF_HAS_DNSINFO) {
2129 		n = letoh32(ic->ipv6_ndnssrv);
2130 		off = letoh32(ic->ipv6_dnssrvoffs);
2131 		i = 0;
2132 		while (n-- > 0) {
2133 			if (off + sizeof (addr6) > len)
2134 				break;
2135 			memcpy(&addr6, data + off, sizeof(addr6));
2136 			if (i < UMB_MAX_DNSSRV)
2137 				sc->sc_info.ipv6dns[i++] = addr6;
2138 			off += sizeof(addr6);
2139 			if (ifp->if_flags & IFF_DEBUG) {
2140 				char str[INET6_ADDRSTRLEN];
2141 				log(LOG_INFO, "%s: IPv6 nameserver %s\n",
2142 				    DEVNAM(ifp->if_softc), inet_ntop(AF_INET6,
2143 				    &addr6, str, sizeof(str)));
2144 			}
2145 		}
2146 		umb_send_inet_proposal(sc, AF_INET6);
2147 	}
2148 
2149 	if ((avail_v6 & MBIM_IPCONF_HAS_MTUINFO)) {
2150 		val = letoh32(ic->ipv6_mtu);
2151 		if (ifp->if_hardmtu != val && val <= sc->sc_maxpktlen) {
2152 			hasmtu = 1;
2153 			ifp->if_hardmtu = val;
2154 			if (ifp->if_mtu > val)
2155 				ifp->if_mtu = val;
2156 		}
2157 	}
2158 #endif
2159 
2160 done:
2161 	if (hasmtu && (ifp->if_flags & IFF_DEBUG))
2162 		log(LOG_INFO, "%s: MTU %d\n", DEVNAM(sc), ifp->if_hardmtu);
2163 
2164 	if (state != -1)
2165 		umb_newstate(sc, state, 0);
2166 
2167 	splx(s);
2168 	return 1;
2169 }
2170 
2171 void
2172 umb_rx(struct umb_softc *sc)
2173 {
2174 	usbd_setup_xfer(sc->sc_rx_xfer, sc->sc_rx_pipe, sc, sc->sc_rx_buf,
2175 	    sc->sc_rx_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY,
2176 	    USBD_NO_TIMEOUT, umb_rxeof);
2177 	usbd_transfer(sc->sc_rx_xfer);
2178 }
2179 
2180 void
2181 umb_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
2182 {
2183 	struct umb_softc *sc = priv;
2184 	struct ifnet *ifp = GET_IFP(sc);
2185 
2186 	if (usbd_is_dying(sc->sc_udev) || !(ifp->if_flags & IFF_RUNNING))
2187 		return;
2188 
2189 	if (status != USBD_NORMAL_COMPLETION) {
2190 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
2191 			return;
2192 		DPRINTF("%s: rx error: %s\n", DEVNAM(sc), usbd_errstr(status));
2193 		if (status == USBD_STALLED)
2194 			usbd_clear_endpoint_stall_async(sc->sc_rx_pipe);
2195 		if (++sc->sc_rx_nerr > 100) {
2196 			log(LOG_ERR, "%s: too many rx errors, disabling\n",
2197 			    DEVNAM(sc));
2198 			usbd_deactivate(sc->sc_udev);
2199 		}
2200 	} else {
2201 		sc->sc_rx_nerr = 0;
2202 		umb_decap(sc, xfer);
2203 	}
2204 
2205 	umb_rx(sc);
2206 	return;
2207 }
2208 
2209 int
2210 umb_encap(struct umb_softc *sc, int ndgram)
2211 {
2212 	struct ncm_header16 *hdr16 = NULL;
2213 	struct ncm_header32 *hdr32 = NULL;
2214 	struct ncm_pointer16 *ptr16 = NULL;
2215 	struct ncm_pointer32 *ptr32 = NULL;
2216 	struct ncm_pointer16_dgram *dgram16 = NULL;
2217 	struct ncm_pointer32_dgram *dgram32 = NULL;
2218 	int	 offs = 0, plen = 0;
2219 	int	 dgoffs = 0, poffs;
2220 	struct mbuf *m;
2221 	usbd_status  err;
2222 
2223 	/* All size constraints have been validated by the caller! */
2224 
2225 	/* NCM Header */
2226 	switch (sc->sc_ncm_format) {
2227 	case NCM_FORMAT_NTB16:
2228 		hdr16 = sc->sc_tx_buf;
2229 		USETDW(hdr16->dwSignature, NCM_HDR16_SIG);
2230 		USETW(hdr16->wHeaderLength, sizeof (*hdr16));
2231 		USETW(hdr16->wSequence, sc->sc_tx_seq);
2232 		USETW(hdr16->wBlockLength, 0);
2233 		offs = sizeof (*hdr16);
2234 		break;
2235 	case NCM_FORMAT_NTB32:
2236 		hdr32 = sc->sc_tx_buf;
2237 		USETDW(hdr32->dwSignature, NCM_HDR32_SIG);
2238 		USETW(hdr32->wHeaderLength, sizeof (*hdr32));
2239 		USETW(hdr32->wSequence, sc->sc_tx_seq);
2240 		USETDW(hdr32->dwBlockLength, 0);
2241 		offs = sizeof (*hdr32);
2242 		break;
2243 	}
2244 	offs += umb_padding(sc->sc_tx_buf, sc->sc_tx_bufsz, offs,
2245 	    sc->sc_align, 0);
2246 
2247 	if (sc->sc_flags & UMBFLG_NDP_AT_END) {
2248 		dgoffs = offs;
2249 
2250 		/*
2251 		 * Calculate space needed for datagrams.
2252 		 *
2253 		 * XXX cannot use ml_len(&sc->sc_tx_ml), since it ignores
2254 		 *	the padding requirements.
2255 		 */
2256 		poffs = dgoffs;
2257 		MBUF_LIST_FOREACH(&sc->sc_tx_ml, m) {
2258 			poffs += umb_padding(sc->sc_tx_buf, sc->sc_tx_bufsz,
2259 			    poffs, sc->sc_ndp_div, sc->sc_ndp_remainder);
2260 			poffs += m->m_pkthdr.len;
2261 		}
2262 		poffs += umb_padding(sc->sc_tx_buf, sc->sc_tx_bufsz,
2263 		    poffs, sc->sc_ndp_div, sc->sc_ndp_remainder);
2264 	} else
2265 		poffs = offs;
2266 
2267 	/* NCM Pointer */
2268 	switch (sc->sc_ncm_format) {
2269 	case NCM_FORMAT_NTB16:
2270 		USETW(hdr16->wNdpIndex, poffs);
2271 		ptr16 = (struct ncm_pointer16 *)(sc->sc_tx_buf + poffs);
2272 		plen = sizeof(*ptr16) + ndgram * sizeof(*dgram16);
2273 		USETDW(ptr16->dwSignature, MBIM_NCM_NTH16_SIG(umb_session_id));
2274 		USETW(ptr16->wLength, plen);
2275 		USETW(ptr16->wNextNdpIndex, 0);
2276 		dgram16 = ptr16->dgram;
2277 		break;
2278 	case NCM_FORMAT_NTB32:
2279 		USETDW(hdr32->dwNdpIndex, poffs);
2280 		ptr32 = (struct ncm_pointer32 *)(sc->sc_tx_buf + poffs);
2281 		plen = sizeof(*ptr32) + ndgram * sizeof(*dgram32);
2282 		USETDW(ptr32->dwSignature, MBIM_NCM_NTH32_SIG(umb_session_id));
2283 		USETW(ptr32->wLength, plen);
2284 		USETW(ptr32->wReserved6, 0);
2285 		USETDW(ptr32->dwNextNdpIndex, 0);
2286 		USETDW(ptr32->dwReserved12, 0);
2287 		dgram32 = ptr32->dgram;
2288 		break;
2289 	}
2290 
2291 	if (!(sc->sc_flags & UMBFLG_NDP_AT_END))
2292 		dgoffs = offs + plen;
2293 
2294 	/* Encap mbufs to NCM dgrams */
2295 	sc->sc_tx_seq++;
2296 	while ((m = ml_dequeue(&sc->sc_tx_ml)) != NULL) {
2297 		dgoffs += umb_padding(sc->sc_tx_buf, sc->sc_tx_bufsz, dgoffs,
2298 		    sc->sc_ndp_div, sc->sc_ndp_remainder);
2299 		switch (sc->sc_ncm_format) {
2300 		case NCM_FORMAT_NTB16:
2301 			USETW(dgram16->wDatagramIndex, dgoffs);
2302 			USETW(dgram16->wDatagramLen, m->m_pkthdr.len);
2303 			dgram16++;
2304 			break;
2305 		case NCM_FORMAT_NTB32:
2306 			USETDW(dgram32->dwDatagramIndex, dgoffs);
2307 			USETDW(dgram32->dwDatagramLen, m->m_pkthdr.len);
2308 			dgram32++;
2309 			break;
2310 		}
2311 		m_copydata(m, 0, m->m_pkthdr.len, sc->sc_tx_buf + dgoffs);
2312 		dgoffs += m->m_pkthdr.len;
2313 		m_freem(m);
2314 	}
2315 
2316 	if (sc->sc_flags & UMBFLG_NDP_AT_END)
2317 		offs = poffs + plen;
2318 	else
2319 		offs = dgoffs;
2320 
2321 	/* Terminating pointer and datagram size */
2322 	switch (sc->sc_ncm_format) {
2323 	case NCM_FORMAT_NTB16:
2324 		USETW(dgram16->wDatagramIndex, 0);
2325 		USETW(dgram16->wDatagramLen, 0);
2326 		USETW(hdr16->wBlockLength, offs);
2327 		KASSERT(dgram16 - ptr16->dgram == ndgram);
2328 		break;
2329 	case NCM_FORMAT_NTB32:
2330 		USETDW(dgram32->dwDatagramIndex, 0);
2331 		USETDW(dgram32->dwDatagramLen, 0);
2332 		USETDW(hdr32->dwBlockLength, offs);
2333 		KASSERT(dgram32 - ptr32->dgram == ndgram);
2334 		break;
2335 	}
2336 
2337 	DPRINTFN(3, "%s: encap %d bytes\n", DEVNAM(sc), offs);
2338 	DDUMPN(5, sc->sc_tx_buf, offs);
2339 	KASSERT(offs <= sc->sc_tx_bufsz);
2340 
2341 	usbd_setup_xfer(sc->sc_tx_xfer, sc->sc_tx_pipe, sc, sc->sc_tx_buf, offs,
2342 	    USBD_FORCE_SHORT_XFER | USBD_NO_COPY, umb_xfer_tout, umb_txeof);
2343 	err = usbd_transfer(sc->sc_tx_xfer);
2344 	if (err != USBD_IN_PROGRESS) {
2345 		DPRINTF("%s: start tx error: %s\n", DEVNAM(sc),
2346 		    usbd_errstr(err));
2347 		ml_purge(&sc->sc_tx_ml);
2348 		return 0;
2349 	}
2350 	return 1;
2351 }
2352 
2353 void
2354 umb_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
2355 {
2356 	struct umb_softc *sc = priv;
2357 	struct ifnet *ifp = GET_IFP(sc);
2358 	int	 s;
2359 
2360 	s = splnet();
2361 	ml_purge(&sc->sc_tx_ml);
2362 	ifq_clr_oactive(&ifp->if_snd);
2363 	ifp->if_timer = 0;
2364 
2365 	if (status != USBD_NORMAL_COMPLETION) {
2366 		if (status != USBD_NOT_STARTED && status != USBD_CANCELLED) {
2367 			ifp->if_oerrors++;
2368 			DPRINTF("%s: tx error: %s\n", DEVNAM(sc),
2369 			    usbd_errstr(status));
2370 			if (status == USBD_STALLED)
2371 				usbd_clear_endpoint_stall_async(sc->sc_tx_pipe);
2372 		}
2373 	}
2374 	if (ifq_empty(&ifp->if_snd) == 0)
2375 		umb_start(ifp);
2376 
2377 	splx(s);
2378 }
2379 
2380 void
2381 umb_decap(struct umb_softc *sc, struct usbd_xfer *xfer)
2382 {
2383 	struct ifnet *ifp = GET_IFP(sc);
2384 	int	 s;
2385 	void	*buf;
2386 	uint32_t len, af = 0;
2387 	char	*dp;
2388 	struct ncm_header16 *hdr16;
2389 	struct ncm_header32 *hdr32;
2390 	struct ncm_pointer16 *ptr16;
2391 	struct ncm_pointer16_dgram *dgram16;
2392 	struct ncm_pointer32_dgram *dgram32;
2393 	uint32_t hsig, psig;
2394 	int	 blen;
2395 	int	 ptrlen, ptroff, dgentryoff;
2396 	uint32_t doff, dlen;
2397 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
2398 	struct mbuf *m;
2399 
2400 	usbd_get_xfer_status(xfer, NULL, &buf, &len, NULL);
2401 	DPRINTFN(4, "%s: recv %d bytes\n", DEVNAM(sc), len);
2402 	DDUMPN(5, buf, len);
2403 	s = splnet();
2404 	if (len < sizeof (*hdr16))
2405 		goto toosmall;
2406 
2407 	hdr16 = (struct ncm_header16 *)buf;
2408 	hsig = UGETDW(hdr16->dwSignature);
2409 
2410 	switch (hsig) {
2411 	case NCM_HDR16_SIG:
2412 		blen = UGETW(hdr16->wBlockLength);
2413 		ptroff = UGETW(hdr16->wNdpIndex);
2414 		if (UGETW(hdr16->wHeaderLength) != sizeof (*hdr16)) {
2415 			DPRINTF("%s: bad header len %d for NTH16 (exp %zu)\n",
2416 			    DEVNAM(sc), UGETW(hdr16->wHeaderLength),
2417 			    sizeof (*hdr16));
2418 			goto fail;
2419 		}
2420 		break;
2421 	case NCM_HDR32_SIG:
2422 		if (len < sizeof (*hdr32))
2423 			goto toosmall;
2424 		hdr32 = (struct ncm_header32 *)hdr16;
2425 		blen = UGETDW(hdr32->dwBlockLength);
2426 		ptroff = UGETDW(hdr32->dwNdpIndex);
2427 		if (UGETW(hdr32->wHeaderLength) != sizeof (*hdr32)) {
2428 			DPRINTF("%s: bad header len %d for NTH32 (exp %zu)\n",
2429 			    DEVNAM(sc), UGETW(hdr32->wHeaderLength),
2430 			    sizeof (*hdr32));
2431 			goto fail;
2432 		}
2433 		break;
2434 	default:
2435 		DPRINTF("%s: unsupported NCM header signature (0x%08x)\n",
2436 		    DEVNAM(sc), hsig);
2437 		goto fail;
2438 	}
2439 	if (blen != 0 && len < blen) {
2440 		DPRINTF("%s: bad NTB len (%d) for %d bytes of data\n",
2441 		    DEVNAM(sc), blen, len);
2442 		goto fail;
2443 	}
2444 
2445 	ptr16 = (struct ncm_pointer16 *)(buf + ptroff);
2446 	psig = UGETDW(ptr16->dwSignature);
2447 	ptrlen = UGETW(ptr16->wLength);
2448 	if (len < ptrlen + ptroff)
2449 		goto toosmall;
2450 	if (!MBIM_NCM_NTH16_ISISG(psig) && !MBIM_NCM_NTH32_ISISG(psig)) {
2451 		DPRINTF("%s: unsupported NCM pointer signature (0x%08x)\n",
2452 		    DEVNAM(sc), psig);
2453 		goto fail;
2454 	}
2455 
2456 	switch (hsig) {
2457 	case NCM_HDR16_SIG:
2458 		dgentryoff = offsetof(struct ncm_pointer16, dgram);
2459 		break;
2460 	case NCM_HDR32_SIG:
2461 		dgentryoff = offsetof(struct ncm_pointer32, dgram);
2462 		break;
2463 	default:
2464 		goto fail;
2465 	}
2466 
2467 	while (dgentryoff < ptrlen) {
2468 		switch (hsig) {
2469 		case NCM_HDR16_SIG:
2470 			if (ptroff + dgentryoff < sizeof (*dgram16))
2471 				goto done;
2472 			dgram16 = (struct ncm_pointer16_dgram *)
2473 			    (buf + ptroff + dgentryoff);
2474 			dgentryoff += sizeof (*dgram16);
2475 			dlen = UGETW(dgram16->wDatagramLen);
2476 			doff = UGETW(dgram16->wDatagramIndex);
2477 			break;
2478 		case NCM_HDR32_SIG:
2479 			if (ptroff + dgentryoff < sizeof (*dgram32))
2480 				goto done;
2481 			dgram32 = (struct ncm_pointer32_dgram *)
2482 			    (buf + ptroff + dgentryoff);
2483 			dgentryoff += sizeof (*dgram32);
2484 			dlen = UGETDW(dgram32->dwDatagramLen);
2485 			doff = UGETDW(dgram32->dwDatagramIndex);
2486 			break;
2487 		default:
2488 			ifp->if_ierrors++;
2489 			goto done;
2490 		}
2491 
2492 		/* Terminating zero entry */
2493 		if (dlen == 0 || doff == 0)
2494 			break;
2495 		if (len < dlen + doff) {
2496 			/* Skip giant datagram but continue processing */
2497 			DPRINTF("%s: datagram too large (%d @ off %d)\n",
2498 			    DEVNAM(sc), dlen, doff);
2499 			continue;
2500 		}
2501 
2502 		dp = buf + doff;
2503 		DPRINTFN(3, "%s: decap %d bytes\n", DEVNAM(sc), dlen);
2504 		m = m_devget(dp, dlen, sizeof(uint32_t));
2505 		if (m == NULL) {
2506 			ifp->if_iqdrops++;
2507 			continue;
2508 		}
2509 		m = m_prepend(m, sizeof(uint32_t), M_DONTWAIT);
2510 		if (m == NULL) {
2511 			ifp->if_iqdrops++;
2512 			continue;
2513 		}
2514 		switch (*dp & 0xf0) {
2515 		case 4 << 4:
2516 			af = htonl(AF_INET);
2517 			break;
2518 		case 6 << 4:
2519 			af = htonl(AF_INET6);
2520 			break;
2521 		}
2522 		*mtod(m, uint32_t *) = af;
2523 		ml_enqueue(&ml, m);
2524 	}
2525 done:
2526 	if_input(ifp, &ml);
2527 	splx(s);
2528 	return;
2529 toosmall:
2530 	DPRINTF("%s: packet too small (%d)\n", DEVNAM(sc), len);
2531 fail:
2532 	ifp->if_ierrors++;
2533 	splx(s);
2534 }
2535 
2536 usbd_status
2537 umb_send_encap_command(struct umb_softc *sc, void *data, int len)
2538 {
2539 	struct usbd_xfer *xfer;
2540 	usb_device_request_t req;
2541 	char *buf;
2542 
2543 	if (len > sc->sc_ctrl_len)
2544 		return USBD_INVAL;
2545 
2546 	if ((xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL)
2547 		return USBD_NOMEM;
2548 	if ((buf = usbd_alloc_buffer(xfer, len)) == NULL) {
2549 		usbd_free_xfer(xfer);
2550 		return USBD_NOMEM;
2551 	}
2552 	memcpy(buf, data, len);
2553 
2554 	/* XXX FIXME: if (total len > sc->sc_ctrl_len) => must fragment */
2555 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
2556 	req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
2557 	USETW(req.wValue, 0);
2558 	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2559 	USETW(req.wLength, len);
2560 	DELAY(umb_delay);
2561 	return usbd_request_async(xfer, &req, NULL, NULL);
2562 }
2563 
2564 int
2565 umb_get_encap_response(struct umb_softc *sc, void *buf, int *len)
2566 {
2567 	usb_device_request_t req;
2568 	usbd_status err;
2569 
2570 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
2571 	req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
2572 	USETW(req.wValue, 0);
2573 	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2574 	USETW(req.wLength, *len);
2575 	/* XXX FIXME: re-assemble fragments */
2576 
2577 	DELAY(umb_delay);
2578 	err = usbd_do_request_flags(sc->sc_udev, &req, buf, USBD_SHORT_XFER_OK,
2579 	    len, umb_xfer_tout);
2580 	if (err == USBD_NORMAL_COMPLETION)
2581 		return 1;
2582 	DPRINTF("%s: ctrl recv: %s\n", DEVNAM(sc), usbd_errstr(err));
2583 	return 0;
2584 }
2585 
2586 void
2587 umb_ctrl_msg(struct umb_softc *sc, uint32_t req, void *data, int len)
2588 {
2589 	struct ifnet *ifp = GET_IFP(sc);
2590 	uint32_t tid;
2591 	struct mbim_msghdr *hdr = data;
2592 	usbd_status err;
2593 	int	 s;
2594 
2595 	assertwaitok();
2596 	if (usbd_is_dying(sc->sc_udev))
2597 		return;
2598 	if (len < sizeof (*hdr))
2599 		return;
2600 	tid = ++sc->sc_tid;
2601 
2602 	hdr->type = htole32(req);
2603 	hdr->len = htole32(len);
2604 	hdr->tid = htole32(tid);
2605 
2606 #ifdef UMB_DEBUG
2607 	if (umb_debug) {
2608 		const char *op, *str;
2609 		if (req == MBIM_COMMAND_MSG) {
2610 			struct mbim_h2f_cmd *c = data;
2611 			if (letoh32(c->op) == MBIM_CMDOP_SET)
2612 				op = "set";
2613 			else
2614 				op = "qry";
2615 			str = umb_cid2str(letoh32(c->cid));
2616 		} else {
2617 			op = "snd";
2618 			str = umb_request2str(req);
2619 		}
2620 		DPRINTF("%s: -> %s %s (tid %u)\n", DEVNAM(sc), op, str, tid);
2621 	}
2622 #endif
2623 	s = splusb();
2624 	err = umb_send_encap_command(sc, data, len);
2625 	splx(s);
2626 	if (err != USBD_NORMAL_COMPLETION) {
2627 		if (ifp->if_flags & IFF_DEBUG)
2628 			log(LOG_ERR, "%s: send %s msg (tid %u) failed: %s\n",
2629 			    DEVNAM(sc), umb_request2str(req), tid,
2630 			    usbd_errstr(err));
2631 
2632 		/* will affect other transactions, too */
2633 		usbd_abort_pipe(sc->sc_udev->default_pipe);
2634 	} else {
2635 		DPRINTFN(2, "%s: sent %s (tid %u)\n", DEVNAM(sc),
2636 		    umb_request2str(req), tid);
2637 		DDUMPN(3, data, len);
2638 	}
2639 	return;
2640 }
2641 
2642 void
2643 umb_open(struct umb_softc *sc)
2644 {
2645 	struct mbim_h2f_openmsg msg;
2646 
2647 	memset(&msg, 0, sizeof (msg));
2648 	msg.maxlen = htole32(sc->sc_ctrl_len);
2649 	umb_ctrl_msg(sc, MBIM_OPEN_MSG, &msg, sizeof (msg));
2650 	return;
2651 }
2652 
2653 void
2654 umb_close(struct umb_softc *sc)
2655 {
2656 	struct mbim_h2f_closemsg msg;
2657 
2658 	memset(&msg, 0, sizeof (msg));
2659 	umb_ctrl_msg(sc, MBIM_CLOSE_MSG, &msg, sizeof (msg));
2660 }
2661 
2662 int
2663 umb_setpin(struct umb_softc *sc, int op, int is_puk, void *pin, int pinlen,
2664     void *newpin, int newpinlen)
2665 {
2666 	struct mbim_cid_pin cp;
2667 	int	 off;
2668 
2669 	if (pinlen == 0)
2670 		return 0;
2671 	if (pinlen < 0 || pinlen > MBIM_PIN_MAXLEN ||
2672 	    newpinlen < 0 || newpinlen > MBIM_PIN_MAXLEN ||
2673 	    op < 0 || op > MBIM_PIN_OP_CHANGE ||
2674 	    (is_puk && op != MBIM_PIN_OP_ENTER))
2675 		return EINVAL;
2676 
2677 	memset(&cp, 0, sizeof (cp));
2678 	cp.type = htole32(is_puk ? MBIM_PIN_TYPE_PUK1 : MBIM_PIN_TYPE_PIN1);
2679 
2680 	off = offsetof(struct mbim_cid_pin, data);
2681 	if (!umb_addstr(&cp, sizeof (cp), &off, pin, pinlen,
2682 	    &cp.pin_offs, &cp.pin_size))
2683 		return EINVAL;
2684 
2685 	cp.op  = htole32(op);
2686 	if (newpinlen) {
2687 		if (!umb_addstr(&cp, sizeof (cp), &off, newpin, newpinlen,
2688 		    &cp.newpin_offs, &cp.newpin_size))
2689 			return EINVAL;
2690 	} else {
2691 		if ((op == MBIM_PIN_OP_CHANGE) || is_puk)
2692 			return EINVAL;
2693 		if (!umb_addstr(&cp, sizeof (cp), &off, NULL, 0,
2694 		    &cp.newpin_offs, &cp.newpin_size))
2695 			return EINVAL;
2696 	}
2697 	umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_SET, &cp, off);
2698 	return 0;
2699 }
2700 
2701 void
2702 umb_setdataclass(struct umb_softc *sc)
2703 {
2704 	struct mbim_cid_registration_state rs;
2705 	uint32_t	 classes;
2706 
2707 	if (sc->sc_info.supportedclasses == MBIM_DATACLASS_NONE)
2708 		return;
2709 
2710 	memset(&rs, 0, sizeof (rs));
2711 	rs.regaction = htole32(MBIM_REGACTION_AUTOMATIC);
2712 	classes = sc->sc_info.supportedclasses;
2713 	if (sc->sc_info.preferredclasses != MBIM_DATACLASS_NONE)
2714 		classes &= sc->sc_info.preferredclasses;
2715 	rs.data_class = htole32(classes);
2716 	umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_SET, &rs, sizeof (rs));
2717 }
2718 
2719 void
2720 umb_radio(struct umb_softc *sc, int on)
2721 {
2722 	struct mbim_cid_radio_state s;
2723 
2724 	DPRINTF("%s: set radio %s\n", DEVNAM(sc), on ? "on" : "off");
2725 	memset(&s, 0, sizeof (s));
2726 	s.state = htole32(on ? MBIM_RADIO_STATE_ON : MBIM_RADIO_STATE_OFF);
2727 	umb_cmd(sc, MBIM_CID_RADIO_STATE, MBIM_CMDOP_SET, &s, sizeof (s));
2728 }
2729 
2730 void
2731 umb_allocate_cid(struct umb_softc *sc)
2732 {
2733 	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2734 	    umb_qmi_alloc_cid, sizeof (umb_qmi_alloc_cid), umb_uuid_qmi_mbim);
2735 }
2736 
2737 void
2738 umb_send_fcc_auth(struct umb_softc *sc)
2739 {
2740 	uint8_t	 fccauth[sizeof (umb_qmi_fcc_auth)];
2741 
2742 	if (sc->sc_cid == -1) {
2743 		DPRINTF("%s: missing CID, cannot send FCC auth\n", DEVNAM(sc));
2744 		umb_allocate_cid(sc);
2745 		return;
2746 	}
2747 	memcpy(fccauth, umb_qmi_fcc_auth, sizeof (fccauth));
2748 	fccauth[UMB_QMI_CID_OFFS] = sc->sc_cid;
2749 	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2750 	    fccauth, sizeof (fccauth), umb_uuid_qmi_mbim);
2751 }
2752 
2753 void
2754 umb_packet_service(struct umb_softc *sc, int attach)
2755 {
2756 	struct mbim_cid_packet_service	s;
2757 
2758 	DPRINTF("%s: %s packet service\n", DEVNAM(sc),
2759 	    attach ? "attach" : "detach");
2760 	memset(&s, 0, sizeof (s));
2761 	s.action = htole32(attach ?
2762 	    MBIM_PKTSERVICE_ACTION_ATTACH : MBIM_PKTSERVICE_ACTION_DETACH);
2763 	umb_cmd(sc, MBIM_CID_PACKET_SERVICE, MBIM_CMDOP_SET, &s, sizeof (s));
2764 }
2765 
2766 void
2767 umb_connect(struct umb_softc *sc)
2768 {
2769 	struct ifnet *ifp = GET_IFP(sc);
2770 
2771 	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
2772 		log(LOG_INFO, "%s: connection disabled in roaming network\n",
2773 		    DEVNAM(sc));
2774 		return;
2775 	}
2776 	if (ifp->if_flags & IFF_DEBUG)
2777 		log(LOG_DEBUG, "%s: connecting ...\n", DEVNAM(sc));
2778 	umb_send_connect(sc, MBIM_CONNECT_ACTIVATE);
2779 }
2780 
2781 void
2782 umb_disconnect(struct umb_softc *sc)
2783 {
2784 	struct ifnet *ifp = GET_IFP(sc);
2785 
2786 	if (ifp->if_flags & IFF_DEBUG)
2787 		log(LOG_DEBUG, "%s: disconnecting ...\n", DEVNAM(sc));
2788 	umb_send_connect(sc, MBIM_CONNECT_DEACTIVATE);
2789 }
2790 
2791 void
2792 umb_send_connect(struct umb_softc *sc, int command)
2793 {
2794 	struct mbim_cid_connect *c;
2795 	int	 off;
2796 
2797 	/* Too large or the stack */
2798 	c = malloc(sizeof (*c), M_USBDEV, M_WAIT|M_ZERO);
2799 	c->sessionid = htole32(umb_session_id);
2800 	c->command = htole32(command);
2801 	off = offsetof(struct mbim_cid_connect, data);
2802 	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.apn,
2803 	    sc->sc_info.apnlen, &c->access_offs, &c->access_size))
2804 		goto done;
2805 	/* XXX FIXME: support user name and passphrase */
2806 	c->user_offs = htole32(0);
2807 	c->user_size = htole32(0);
2808 	c->passwd_offs = htole32(0);
2809 	c->passwd_size = htole32(0);
2810 	c->authprot = htole32(MBIM_AUTHPROT_NONE);
2811 	c->compression = htole32(MBIM_COMPRESSION_NONE);
2812 	c->iptype = htole32(MBIM_CONTEXT_IPTYPE_IPV4);
2813 #ifdef INET6
2814 	/* XXX FIXME: support IPv6-only mode, too */
2815 	if ((sc->sc_flags & UMBFLG_NO_INET6) == 0 &&
2816 	    in6ifa_ifpforlinklocal(GET_IFP(sc), 0) != NULL)
2817 		c->iptype = htole32(MBIM_CONTEXT_IPTYPE_IPV4V6);
2818 #endif
2819 	memcpy(c->context, umb_uuid_context_internet, sizeof (c->context));
2820 	umb_cmd(sc, MBIM_CID_CONNECT, MBIM_CMDOP_SET, c, off);
2821 done:
2822 	free(c, M_USBDEV, sizeof (*c));
2823 	return;
2824 }
2825 
2826 void
2827 umb_qry_ipconfig(struct umb_softc *sc)
2828 {
2829 	struct mbim_cid_ip_configuration_info ipc;
2830 
2831 	memset(&ipc, 0, sizeof (ipc));
2832 	ipc.sessionid = htole32(umb_session_id);
2833 	umb_cmd(sc, MBIM_CID_IP_CONFIGURATION, MBIM_CMDOP_QRY,
2834 	    &ipc, sizeof (ipc));
2835 }
2836 
2837 void
2838 umb_cmd(struct umb_softc *sc, int cid, int op, void *data, int len)
2839 {
2840 	umb_cmd1(sc, cid, op, data, len, umb_uuid_basic_connect);
2841 }
2842 
2843 void
2844 umb_cmd1(struct umb_softc *sc, int cid, int op, void *data, int len,
2845     uint8_t *uuid)
2846 {
2847 	struct mbim_h2f_cmd *cmd;
2848 	int	totlen;
2849 
2850 	/* XXX FIXME support sending fragments */
2851 	if (sizeof (*cmd) + len > sc->sc_ctrl_len) {
2852 		DPRINTF("%s: set %s msg too long: cannot send\n",
2853 		    DEVNAM(sc), umb_cid2str(cid));
2854 		return;
2855 	}
2856 	cmd = sc->sc_ctrl_msg;
2857 	memset(cmd, 0, sizeof (*cmd));
2858 	cmd->frag.nfrag = htole32(1);
2859 	memcpy(cmd->devid, uuid, sizeof (cmd->devid));
2860 	cmd->cid = htole32(cid);
2861 	cmd->op = htole32(op);
2862 	cmd->infolen = htole32(len);
2863 	totlen = sizeof (*cmd);
2864 	if (len > 0) {
2865 		memcpy(cmd + 1, data, len);
2866 		totlen += len;
2867 	}
2868 	umb_ctrl_msg(sc, MBIM_COMMAND_MSG, cmd, totlen);
2869 }
2870 
2871 void
2872 umb_command_done(struct umb_softc *sc, void *data, int len)
2873 {
2874 	struct mbim_f2h_cmddone *cmd = data;
2875 	struct ifnet *ifp = GET_IFP(sc);
2876 	uint32_t status;
2877 	uint32_t cid;
2878 	uint32_t infolen;
2879 	int	 qmimsg = 0;
2880 
2881 	if (len < sizeof (*cmd)) {
2882 		DPRINTF("%s: discard short %s message\n", DEVNAM(sc),
2883 		    umb_request2str(letoh32(cmd->hdr.type)));
2884 		return;
2885 	}
2886 	cid = letoh32(cmd->cid);
2887 	if (memcmp(cmd->devid, umb_uuid_basic_connect, sizeof (cmd->devid))) {
2888 		if (memcmp(cmd->devid, umb_uuid_qmi_mbim,
2889 		    sizeof (cmd->devid))) {
2890 			DPRINTF("%s: discard %s message for other UUID '%s'\n",
2891 			    DEVNAM(sc), umb_request2str(letoh32(cmd->hdr.type)),
2892 			    umb_uuid2str(cmd->devid));
2893 			return;
2894 		} else
2895 			qmimsg = 1;
2896 	}
2897 
2898 	status = letoh32(cmd->status);
2899 	switch (status) {
2900 	case MBIM_STATUS_SUCCESS:
2901 		break;
2902 #ifdef INET6
2903 	case MBIM_STATUS_NO_DEVICE_SUPPORT:
2904 		if ((cid == MBIM_CID_CONNECT) &&
2905 		    (sc->sc_flags & UMBFLG_NO_INET6) == 0) {
2906 			sc->sc_flags |= UMBFLG_NO_INET6;
2907 			if (ifp->if_flags & IFF_DEBUG)
2908 				log(LOG_ERR,
2909 				    "%s: device does not support IPv6\n",
2910 				    DEVNAM(sc));
2911 		}
2912 		/* Re-trigger the connect, this time IPv4 only */
2913 		usb_add_task(sc->sc_udev, &sc->sc_umb_task);
2914 		return;
2915 #endif
2916 	case MBIM_STATUS_NOT_INITIALIZED:
2917 		if (ifp->if_flags & IFF_DEBUG)
2918 			log(LOG_ERR, "%s: SIM not initialized (PIN missing)\n",
2919 			    DEVNAM(sc));
2920 		return;
2921 	case MBIM_STATUS_PIN_REQUIRED:
2922 		sc->sc_info.pin_state = UMB_PIN_REQUIRED;
2923 		/*FALLTHROUGH*/
2924 	default:
2925 		if (ifp->if_flags & IFF_DEBUG)
2926 			log(LOG_ERR, "%s: set/qry %s failed: %s\n", DEVNAM(sc),
2927 			    umb_cid2str(cid), umb_status2str(status));
2928 		return;
2929 	}
2930 
2931 	infolen = letoh32(cmd->infolen);
2932 	if (len < sizeof (*cmd) + infolen) {
2933 		DPRINTF("%s: discard truncated %s message (want %d, got %d)\n",
2934 		    DEVNAM(sc), umb_cid2str(cid),
2935 		    (int)sizeof (*cmd) + infolen, len);
2936 		return;
2937 	}
2938 	if (qmimsg) {
2939 		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED)
2940 			umb_decode_qmi(sc, cmd->info, infolen);
2941 	} else {
2942 		DPRINTFN(2, "%s: set/qry %s done\n", DEVNAM(sc),
2943 		    umb_cid2str(cid));
2944 		umb_decode_cid(sc, cid, cmd->info, infolen);
2945 	}
2946 }
2947 
2948 void
2949 umb_decode_cid(struct umb_softc *sc, uint32_t cid, void *data, int len)
2950 {
2951 	int	 ok = 1;
2952 
2953 	switch (cid) {
2954 	case MBIM_CID_DEVICE_CAPS:
2955 		ok = umb_decode_devices_caps(sc, data, len);
2956 		break;
2957 	case MBIM_CID_SUBSCRIBER_READY_STATUS:
2958 		ok = umb_decode_subscriber_status(sc, data, len);
2959 		break;
2960 	case MBIM_CID_RADIO_STATE:
2961 		ok = umb_decode_radio_state(sc, data, len);
2962 		break;
2963 	case MBIM_CID_PIN:
2964 		ok = umb_decode_pin(sc, data, len);
2965 		break;
2966 	case MBIM_CID_REGISTER_STATE:
2967 		ok = umb_decode_register_state(sc, data, len);
2968 		break;
2969 	case MBIM_CID_PACKET_SERVICE:
2970 		ok = umb_decode_packet_service(sc, data, len);
2971 		break;
2972 	case MBIM_CID_SIGNAL_STATE:
2973 		ok = umb_decode_signal_state(sc, data, len);
2974 		break;
2975 	case MBIM_CID_CONNECT:
2976 		ok = umb_decode_connect_info(sc, data, len);
2977 		break;
2978 	case MBIM_CID_IP_CONFIGURATION:
2979 		ok = umb_decode_ip_configuration(sc, data, len);
2980 		break;
2981 	default:
2982 		/*
2983 		 * Note: the above list is incomplete and only contains
2984 		 *	mandatory CIDs from the BASIC_CONNECT set.
2985 		 *	So alternate values are not unusual.
2986 		 */
2987 		DPRINTFN(4, "%s: ignore %s\n", DEVNAM(sc), umb_cid2str(cid));
2988 		break;
2989 	}
2990 	if (!ok)
2991 		DPRINTF("%s: discard %s with bad info length %d\n",
2992 		    DEVNAM(sc), umb_cid2str(cid), len);
2993 	return;
2994 }
2995 
2996 void
2997 umb_decode_qmi(struct umb_softc *sc, uint8_t *data, int len)
2998 {
2999 	uint8_t	srv;
3000 	uint16_t msg, tlvlen;
3001 	uint32_t val;
3002 
3003 #define UMB_QMI_QMUXLEN		6
3004 	if (len < UMB_QMI_QMUXLEN)
3005 		goto tooshort;
3006 
3007 	srv = data[4];
3008 	data += UMB_QMI_QMUXLEN;
3009 	len -= UMB_QMI_QMUXLEN;
3010 
3011 #define UMB_GET16(p)	((uint16_t)*p | (uint16_t)*(p + 1) << 8)
3012 #define UMB_GET32(p)	((uint32_t)*p | (uint32_t)*(p + 1) << 8 | \
3013 			    (uint32_t)*(p + 2) << 16 |(uint32_t)*(p + 3) << 24)
3014 	switch (srv) {
3015 	case 0:	/* ctl */
3016 #define UMB_QMI_CTLLEN		6
3017 		if (len < UMB_QMI_CTLLEN)
3018 			goto tooshort;
3019 		msg = UMB_GET16(&data[2]);
3020 		tlvlen = UMB_GET16(&data[4]);
3021 		data += UMB_QMI_CTLLEN;
3022 		len -= UMB_QMI_CTLLEN;
3023 		break;
3024 	case 2:	/* dms  */
3025 #define UMB_QMI_DMSLEN		7
3026 		if (len < UMB_QMI_DMSLEN)
3027 			goto tooshort;
3028 		msg = UMB_GET16(&data[3]);
3029 		tlvlen = UMB_GET16(&data[5]);
3030 		data += UMB_QMI_DMSLEN;
3031 		len -= UMB_QMI_DMSLEN;
3032 		break;
3033 	default:
3034 		DPRINTF("%s: discard QMI message for unknown service type %d\n",
3035 		    DEVNAM(sc), srv);
3036 		return;
3037 	}
3038 
3039 	if (len < tlvlen)
3040 		goto tooshort;
3041 
3042 #define UMB_QMI_TLVLEN		3
3043 	while (len > 0) {
3044 		if (len < UMB_QMI_TLVLEN)
3045 			goto tooshort;
3046 		tlvlen = UMB_GET16(&data[1]);
3047 		if (len < UMB_QMI_TLVLEN + tlvlen)
3048 			goto tooshort;
3049 		switch (data[0]) {
3050 		case 1:	/* allocation info */
3051 			if (msg == 0x0022) {	/* Allocate CID */
3052 				if (tlvlen != 2 || data[3] != 2) /* dms */
3053 					break;
3054 				sc->sc_cid = data[4];
3055 				DPRINTF("%s: QMI CID %d allocated\n",
3056 				    DEVNAM(sc), sc->sc_cid);
3057 				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
3058 			}
3059 			break;
3060 		case 2:	/* response */
3061 			if (tlvlen != sizeof (val))
3062 				break;
3063 			val = UMB_GET32(&data[3]);
3064 			switch (msg) {
3065 			case 0x0022:	/* Allocate CID */
3066 				if (val != 0) {
3067 					log(LOG_ERR, "%s: allocation of QMI CID"
3068 					    " failed, error 0x%x\n", DEVNAM(sc),
3069 					    val);
3070 					/* XXX how to proceed? */
3071 					return;
3072 				}
3073 				break;
3074 			case 0x555f:	/* Send FCC Authentication */
3075 				if (val == 0)
3076 					DPRINTF("%s: send FCC "
3077 					    "Authentication succeeded\n",
3078 					    DEVNAM(sc));
3079 				else if (val == 0x001a0001)
3080 					DPRINTF("%s: FCC Authentication "
3081 					    "not required\n", DEVNAM(sc));
3082 				else
3083 					log(LOG_INFO, "%s: send FCC "
3084 					    "Authentication failed, "
3085 					    "error 0x%x\n", DEVNAM(sc), val);
3086 
3087 				/* FCC Auth is needed only once after power-on*/
3088 				sc->sc_flags &= ~UMBFLG_FCC_AUTH_REQUIRED;
3089 
3090 				/* Try to proceed anyway */
3091 				DPRINTF("%s: init: turning radio on ...\n",
3092 				    DEVNAM(sc));
3093 				umb_radio(sc, 1);
3094 				break;
3095 			default:
3096 				break;
3097 			}
3098 			break;
3099 		default:
3100 			break;
3101 		}
3102 		data += UMB_QMI_TLVLEN + tlvlen;
3103 		len -= UMB_QMI_TLVLEN + tlvlen;
3104 	}
3105 	return;
3106 
3107 tooshort:
3108 	DPRINTF("%s: discard short QMI message\n", DEVNAM(sc));
3109 	return;
3110 }
3111 
3112 void
3113 umb_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
3114 {
3115 	struct umb_softc *sc = priv;
3116 	struct ifnet *ifp = GET_IFP(sc);
3117 	int	 total_len;
3118 
3119 	if (status != USBD_NORMAL_COMPLETION) {
3120 		DPRINTF("%s: notification error: %s\n", DEVNAM(sc),
3121 		    usbd_errstr(status));
3122 		if (status == USBD_STALLED)
3123 			usbd_clear_endpoint_stall_async(sc->sc_ctrl_pipe);
3124 		return;
3125 	}
3126 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
3127 	if (total_len < UCDC_NOTIFICATION_LENGTH) {
3128 		DPRINTF("%s: short notification (%d<%d)\n", DEVNAM(sc),
3129 		    total_len, UCDC_NOTIFICATION_LENGTH);
3130 		    return;
3131 	}
3132 	if (sc->sc_intr_msg.bmRequestType != UCDC_NOTIFICATION) {
3133 		DPRINTF("%s: unexpected notification (type=0x%02x)\n",
3134 		    DEVNAM(sc), sc->sc_intr_msg.bmRequestType);
3135 		return;
3136 	}
3137 
3138 	switch (sc->sc_intr_msg.bNotification) {
3139 	case UCDC_N_NETWORK_CONNECTION:
3140 		if (ifp->if_flags & IFF_DEBUG)
3141 			log(LOG_DEBUG, "%s: network %sconnected\n", DEVNAM(sc),
3142 			    UGETW(sc->sc_intr_msg.wValue) ? "" : "dis");
3143 		break;
3144 	case UCDC_N_RESPONSE_AVAILABLE:
3145 		DPRINTFN(2, "%s: umb_intr: response available\n", DEVNAM(sc));
3146 		++sc->sc_nresp;
3147 		usb_add_task(sc->sc_udev, &sc->sc_get_response_task);
3148 		break;
3149 	case UCDC_N_CONNECTION_SPEED_CHANGE:
3150 		DPRINTFN(2, "%s: umb_intr: connection speed changed\n",
3151 		    DEVNAM(sc));
3152 		break;
3153 	default:
3154 		DPRINTF("%s: unexpected notification (0x%02x)\n",
3155 		    DEVNAM(sc), sc->sc_intr_msg.bNotification);
3156 		break;
3157 	}
3158 }
3159 
3160 /*
3161  * Diagnostic routines
3162  */
3163 #ifdef UMB_DEBUG
3164 char *
3165 umb_uuid2str(uint8_t uuid[MBIM_UUID_LEN])
3166 {
3167 	static char uuidstr[2 * MBIM_UUID_LEN + 5];
3168 
3169 #define UUID_BFMT	"%02X"
3170 #define UUID_SEP	"-"
3171 	snprintf(uuidstr, sizeof (uuidstr),
3172 	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_SEP
3173 	    UUID_BFMT UUID_BFMT UUID_SEP
3174 	    UUID_BFMT UUID_BFMT UUID_SEP
3175 	    UUID_BFMT UUID_BFMT UUID_SEP
3176 	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT,
3177 	    uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
3178 	    uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
3179 	    uuid[12], uuid[13], uuid[14], uuid[15]);
3180 	return uuidstr;
3181 }
3182 
3183 void
3184 umb_dump(void *buf, int len)
3185 {
3186 	int	 i = 0;
3187 	uint8_t	*c = buf;
3188 
3189 	if (len == 0)
3190 		return;
3191 	while (i < len) {
3192 		if ((i % 16) == 0) {
3193 			if (i > 0)
3194 				addlog("\n");
3195 			log(LOG_DEBUG, "%4d:  ", i);
3196 		}
3197 		addlog(" %02x", *c);
3198 		c++;
3199 		i++;
3200 	}
3201 	addlog("\n");
3202 }
3203 #endif /* UMB_DEBUG */
3204