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