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