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