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