xref: /freebsd/sys/dev/usb/net/if_umb.c (revision e921d2842ee8ca9e3dae8952e1cf2645cee785aa)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Original copyright (c) 2016 genua mbH (OpenBSD version)
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * Copyright (c) 2022 ADISTA SAS (re-write for FreeBSD)
19  *
20  * Re-write for FreeBSD by Pierre Pronchery <pierre@defora.net>
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions are met:
24  *
25  * - Redistributions of source code must retain the above copyright notice,
26  *   this list of conditions and the following disclaimer.
27  * - Redistributions in binary form must reproduce the above copyright notice,
28  *   this list of conditions and the following disclaimer in the documentation
29  *   and/or other materials provided with the distribution.
30  * - Neither the name of the copyright holder nor the names of its contributors
31  *   may be used to endorse or promote products derived from this software
32  *   without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
35  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
38  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44  * POSSIBILITY OF SUCH DAMAGE.
45  *
46  * $NetBSD: if_umb.c,v 1.5 2018/09/20 09:45:16 khorben Exp $
47  * $OpenBSD: if_umb.c,v 1.18 2018/02/19 08:59:52 mpi Exp $
48  */
49 
50 /*
51  * Mobile Broadband Interface Model specification:
52  * http://www.usb.org/developers/docs/devclass_docs/MBIM10Errata1_073013.zip
53  * Compliance testing guide
54  * http://www.usb.org/developers/docs/devclass_docs/MBIM-Compliance-1.0.pdf
55  */
56 
57 #include <sys/param.h>
58 #include <sys/module.h>
59 #include <sys/endian.h>
60 #include <sys/kernel.h>
61 #include <sys/mbuf.h>
62 #include <sys/priv.h>
63 #include <sys/socket.h>
64 #include <sys/sockio.h>
65 #include <sys/systm.h>
66 #include <sys/syslog.h>
67 #include <sys/kernel.h>
68 #include <sys/queue.h>
69 
70 #include <sys/conf.h>
71 #include <sys/bus.h>
72 #include <sys/mutex.h>
73 #include <sys/condvar.h>
74 #include <sys/taskqueue.h>
75 
76 #include <machine/_inttypes.h>
77 
78 #include <net/bpf.h>
79 #include <net/if.h>
80 #include <net/if_media.h>
81 #include <net/if_types.h>
82 #include <net/if_var.h>
83 #include <net/netisr.h>
84 #include <net/route.h>
85 
86 #include <netinet/in.h>
87 #include <netinet/in_var.h>
88 #include <netinet/ip.h>
89 
90 #include <dev/usb/usb.h>
91 #include <dev/usb/usb_cdc.h>
92 #include <dev/usb/usbdi.h>
93 #include <dev/usb/usb_device.h>
94 #include <dev/usb/usb_process.h>
95 #include <dev/usb/usbdi_util.h>
96 #include "usb_if.h"
97 
98 #include "mbim.h"
99 #include "if_umbreg.h"
100 
101 MALLOC_DECLARE(M_MBIM_CID_CONNECT);
102 MALLOC_DEFINE(M_MBIM_CID_CONNECT, "mbim_cid_connect",
103 		"Connection parameters for MBIM");
104 
105 #ifdef UMB_DEBUG
106 #define DPRINTF(x...)							\
107 		do { if (umb_debug) log(LOG_DEBUG, x); } while (0)
108 
109 #define DPRINTFN(n, x...)						\
110 		do { if (umb_debug >= (n)) log(LOG_DEBUG, x); } while (0)
111 
112 #define DDUMPN(n, b, l)							\
113 		do {							\
114 			if (umb_debug >= (n))				\
115 				umb_dump((b), (l));			\
116 		} while (0)
117 
118 const int	 umb_debug = 1;
119 static char	*umb_uuid2str(uint8_t [MBIM_UUID_LEN]);
120 static void	 umb_dump(void *, int);
121 
122 #else
123 #define DPRINTF(x...)		do { } while (0)
124 #define DPRINTFN(n, x...)	do { } while (0)
125 #define DDUMPN(n, b, l)		do { } while (0)
126 #endif
127 
128 #define DEVNAM(sc)		device_get_nameunit((sc)->sc_dev)
129 
130 /*
131  * State change timeout
132  */
133 #define UMB_STATE_CHANGE_TIMEOUT	30
134 
135 /*
136  * State change flags
137  */
138 #define UMB_NS_DONT_DROP	0x0001	/* do not drop below current state */
139 #define UMB_NS_DONT_RAISE	0x0002	/* do not raise below current state */
140 
141 /*
142  * Diagnostic macros
143  */
144 const struct umb_valdescr umb_regstates[] = MBIM_REGSTATE_DESCRIPTIONS;
145 const struct umb_valdescr umb_dataclasses[] = MBIM_DATACLASS_DESCRIPTIONS;
146 const struct umb_valdescr umb_simstate[] = MBIM_SIMSTATE_DESCRIPTIONS;
147 const struct umb_valdescr umb_messages[] = MBIM_MESSAGES_DESCRIPTIONS;
148 const struct umb_valdescr umb_status[] = MBIM_STATUS_DESCRIPTIONS;
149 const struct umb_valdescr umb_cids[] = MBIM_CID_DESCRIPTIONS;
150 const struct umb_valdescr umb_pktstate[] = MBIM_PKTSRV_STATE_DESCRIPTIONS;
151 const struct umb_valdescr umb_actstate[] = MBIM_ACTIVATION_STATE_DESCRIPTIONS;
152 const struct umb_valdescr umb_error[] = MBIM_ERROR_DESCRIPTIONS;
153 const struct umb_valdescr umb_pintype[] = MBIM_PINTYPE_DESCRIPTIONS;
154 const struct umb_valdescr umb_istate[] = UMB_INTERNAL_STATE_DESCRIPTIONS;
155 
156 #define umb_regstate(c)		umb_val2descr(umb_regstates, (c))
157 #define umb_dataclass(c)	umb_val2descr(umb_dataclasses, (c))
158 #define umb_simstate(s)		umb_val2descr(umb_simstate, (s))
159 #define umb_request2str(m)	umb_val2descr(umb_messages, (m))
160 #define umb_status2str(s)	umb_val2descr(umb_status, (s))
161 #define umb_cid2str(c)		umb_val2descr(umb_cids, (c))
162 #define umb_packet_state(s)	umb_val2descr(umb_pktstate, (s))
163 #define umb_activation(s)	umb_val2descr(umb_actstate, (s))
164 #define umb_error2str(e)	umb_val2descr(umb_error, (e))
165 #define umb_pin_type(t)		umb_val2descr(umb_pintype, (t))
166 #define umb_istate(s)		umb_val2descr(umb_istate, (s))
167 
168 static device_probe_t umb_probe;
169 static device_attach_t umb_attach;
170 static device_detach_t umb_detach;
171 static device_suspend_t umb_suspend;
172 static device_resume_t umb_resume;
173 static void	 umb_attach_task(struct usb_proc_msg *);
174 static usb_handle_request_t umb_handle_request;
175 static int	 umb_deactivate(device_t);
176 static void	 umb_ncm_setup(struct umb_softc *, struct usb_config *);
177 static void	 umb_close_bulkpipes(struct umb_softc *);
178 static int	 umb_ioctl(if_t , u_long, caddr_t);
179 static void	 umb_init(void *);
180 static void	 umb_input(if_t , struct mbuf *);
181 static int	 umb_output(if_t , struct mbuf *,
182 		    const struct sockaddr *, struct route *);
183 static void	 umb_start(if_t );
184 static void	 umb_start_task(struct usb_proc_msg *);
185 #if 0
186 static void	 umb_watchdog(if_t );
187 #endif
188 static void	 umb_statechg_timeout(void *);
189 
190 static int	 umb_mediachange(if_t );
191 static void	 umb_mediastatus(if_t , struct ifmediareq *);
192 
193 static void	 umb_add_task(struct umb_softc *sc, usb_proc_callback_t,
194 		    struct usb_proc_msg *, struct usb_proc_msg *, int);
195 static void	 umb_newstate(struct umb_softc *, enum umb_state, int);
196 static void	 umb_state_task(struct usb_proc_msg *);
197 static void	 umb_up(struct umb_softc *);
198 static void	 umb_down(struct umb_softc *, int);
199 
200 static void	 umb_get_response_task(struct usb_proc_msg *);
201 
202 static void	 umb_decode_response(struct umb_softc *, void *, int);
203 static void	 umb_handle_indicate_status_msg(struct umb_softc *, void *,
204 		    int);
205 static void	 umb_handle_opendone_msg(struct umb_softc *, void *, int);
206 static void	 umb_handle_closedone_msg(struct umb_softc *, void *, int);
207 static int	 umb_decode_register_state(struct umb_softc *, void *, int);
208 static int	 umb_decode_devices_caps(struct umb_softc *, void *, int);
209 static int	 umb_decode_subscriber_status(struct umb_softc *, void *, int);
210 static int	 umb_decode_radio_state(struct umb_softc *, void *, int);
211 static int	 umb_decode_pin(struct umb_softc *, void *, int);
212 static int	 umb_decode_packet_service(struct umb_softc *, void *, int);
213 static int	 umb_decode_signal_state(struct umb_softc *, void *, int);
214 static int	 umb_decode_connect_info(struct umb_softc *, void *, int);
215 static int	 umb_decode_ip_configuration(struct umb_softc *, void *, int);
216 static void	 umb_rx(struct umb_softc *);
217 static usb_callback_t umb_rxeof;
218 static void	 umb_rxflush(struct umb_softc *);
219 static int	 umb_encap(struct umb_softc *, struct mbuf *, struct usb_xfer *);
220 static usb_callback_t umb_txeof;
221 static void	 umb_txflush(struct umb_softc *);
222 static void	 umb_decap(struct umb_softc *, struct usb_xfer *, int);
223 
224 static usb_error_t	 umb_send_encap_command(struct umb_softc *, void *, int);
225 static int	 umb_get_encap_response(struct umb_softc *, void *, int *);
226 static void	 umb_ctrl_msg(struct umb_softc *, uint32_t, void *, int);
227 
228 static void	 umb_open(struct umb_softc *);
229 static void	 umb_close(struct umb_softc *);
230 
231 static int	 umb_setpin(struct umb_softc *, int, int, void *, int, void *,
232 		    int);
233 static void	 umb_setdataclass(struct umb_softc *);
234 static void	 umb_radio(struct umb_softc *, int);
235 static void	 umb_allocate_cid(struct umb_softc *);
236 static void	 umb_send_fcc_auth(struct umb_softc *);
237 static void	 umb_packet_service(struct umb_softc *, int);
238 static void	 umb_connect(struct umb_softc *);
239 static void	 umb_disconnect(struct umb_softc *);
240 static void	 umb_send_connect(struct umb_softc *, int);
241 
242 static void	 umb_qry_ipconfig(struct umb_softc *);
243 static void	 umb_cmd(struct umb_softc *, int, int, const void *, int);
244 static void	 umb_cmd1(struct umb_softc *, int, int, const void *, int, uint8_t *);
245 static void	 umb_command_done(struct umb_softc *, void *, int);
246 static void	 umb_decode_cid(struct umb_softc *, uint32_t, void *, int);
247 static void	 umb_decode_qmi(struct umb_softc *, uint8_t *, int);
248 
249 static usb_callback_t umb_intr;
250 
251 static char	*umb_ntop(struct sockaddr *);
252 
253 static const int umb_xfer_tout = USB_DEFAULT_TIMEOUT;
254 
255 static uint8_t	 umb_uuid_basic_connect[] = MBIM_UUID_BASIC_CONNECT;
256 static uint8_t	 umb_uuid_context_internet[] = MBIM_UUID_CONTEXT_INTERNET;
257 static uint8_t	 umb_uuid_qmi_mbim[] = MBIM_UUID_QMI_MBIM;
258 static uint32_t	 umb_session_id = 0;
259 
260 static const struct usb_config umb_config[UMB_N_TRANSFER] = {
261 	[UMB_INTR_RX] = {
262 		.type = UE_INTERRUPT,
263 		.endpoint = UE_ADDR_ANY,
264 		.direction = UE_DIR_IN,
265 		.if_index = 1,
266 		.callback = umb_intr,
267 		.bufsize = sizeof (struct usb_cdc_notification),
268 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1},
269 		.usb_mode = USB_MODE_HOST,
270 	},
271 	[UMB_BULK_RX] = {
272 		.type = UE_BULK,
273 		.endpoint = UE_ADDR_ANY,
274 		.direction = UE_DIR_IN,
275 		.if_index = 0,
276 		.callback = umb_rxeof,
277 		.bufsize = 8 * 1024,
278 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.ext_buffer = 1},
279 		.usb_mode = USB_MODE_HOST,
280 	},
281 	[UMB_BULK_TX] = {
282 		.type = UE_BULK,
283 		.endpoint = UE_ADDR_ANY,
284 		.direction = UE_DIR_OUT,
285 		.if_index = 0,
286 		.callback = umb_txeof,
287 		.bufsize = 8 * 1024,
288 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1},
289 		.timeout = umb_xfer_tout,
290 		.usb_mode = USB_MODE_HOST,
291 	},
292 };
293 
294 static device_method_t umb_methods[] = {
295 	/* USB interface */
296 	DEVMETHOD(usb_handle_request, umb_handle_request),
297 
298 	/* Device interface */
299 	DEVMETHOD(device_probe, umb_probe),
300 	DEVMETHOD(device_attach, umb_attach),
301 	DEVMETHOD(device_detach, umb_detach),
302 	DEVMETHOD(device_suspend, umb_suspend),
303 	DEVMETHOD(device_resume, umb_resume),
304 
305 	DEVMETHOD_END
306 };
307 
308 static driver_t umb_driver = {
309 	.name = "umb",
310 	.methods = umb_methods,
311 	.size = sizeof (struct umb_softc),
312 };
313 
314 MALLOC_DEFINE(M_USB_UMB, "USB UMB", "USB MBIM driver");
315 
316 const int umb_delay = 4000;
317 
318 /*
319  * These devices require an "FCC Authentication" command.
320  */
321 #ifndef USB_VENDOR_SIERRA
322 # define USB_VENDOR_SIERRA	0x1199
323 #endif
324 #ifndef USB_PRODUCT_SIERRA_EM7455
325 # define USB_PRODUCT_SIERRA_EM7455	0x9079
326 #endif
327 const struct usb_device_id umb_fccauth_devs[] = {
328 	{
329 		.match_flag_vendor = 1,
330 		.match_flag_product = 1,
331 		.idVendor = USB_VENDOR_SIERRA,
332 		.idProduct = USB_PRODUCT_SIERRA_EM7455
333 	}
334 };
335 
336 static const uint8_t umb_qmi_alloc_cid[] = {
337 	0x01,
338 	0x0f, 0x00,		/* len */
339 	0x00,			/* QMUX flags */
340 	0x00,			/* service "ctl" */
341 	0x00,			/* CID */
342 	0x00,			/* QMI flags */
343 	0x01,			/* transaction */
344 	0x22, 0x00,		/* msg "Allocate CID" */
345 	0x04, 0x00,		/* TLV len */
346 	0x01, 0x01, 0x00, 0x02	/* TLV */
347 };
348 
349 static const uint8_t umb_qmi_fcc_auth[] = {
350 	0x01,
351 	0x0c, 0x00,		/* len */
352 	0x00,			/* QMUX flags */
353 	0x02,			/* service "dms" */
354 #define UMB_QMI_CID_OFFS	5
355 	0x00,			/* CID (filled in later) */
356 	0x00,			/* QMI flags */
357 	0x01, 0x00,		/* transaction */
358 	0x5f, 0x55,		/* msg "Send FCC Authentication" */
359 	0x00, 0x00		/* TLV len */
360 };
361 
362 static int
umb_probe(device_t dev)363 umb_probe(device_t dev)
364 {
365 	struct usb_attach_arg *uaa = device_get_ivars(dev);
366 	usb_interface_descriptor_t *id;
367 
368 	if (uaa->usb_mode != USB_MODE_HOST)
369 		return (ENXIO);
370 	if ((id = usbd_get_interface_descriptor(uaa->iface)) == NULL)
371 		return (ENXIO);
372 
373 	/*
374 	 * If this function implements NCM, check if alternate setting
375 	 * 1 implements MBIM.
376 	 */
377 	if (id->bInterfaceClass == UICLASS_CDC &&
378 	    id->bInterfaceSubClass ==
379 	    UISUBCLASS_NETWORK_CONTROL_MODEL) {
380 		id = usbd_get_interface_descriptor(
381 				usbd_get_iface(uaa->device,
382 					uaa->info.bIfaceIndex + 1));
383 		if (id == NULL || id->bAlternateSetting != 1)
384 			return (ENXIO);
385 	}
386 
387 #ifndef UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL
388 # define UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL 14
389 #endif
390 	if (id->bInterfaceClass == UICLASS_CDC &&
391 	    id->bInterfaceSubClass ==
392 	    UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL &&
393 	    id->bInterfaceProtocol == 0)
394 		return (BUS_PROBE_SPECIFIC);
395 
396 	return (ENXIO);
397 }
398 
399 static int
umb_attach(device_t dev)400 umb_attach(device_t dev)
401 {
402 	struct umb_softc *sc = device_get_softc(dev);
403 	struct usb_attach_arg *uaa = device_get_ivars(dev);
404 	struct usb_config config[UMB_N_TRANSFER];
405 	int	 v;
406 	const struct usb_cdc_union_descriptor *ud;
407 	const struct mbim_descriptor *md;
408 	int	 i;
409 	usb_interface_descriptor_t *id;
410 	struct usb_interface *iface;
411 	int	 data_ifaceno = -1;
412 	usb_error_t error;
413 
414 	sc->sc_dev = dev;
415 	sc->sc_udev = uaa->device;
416 
417 	memcpy(config, umb_config, sizeof (config));
418 
419 	device_set_usb_desc(dev);
420 
421 	sc->sc_ctrl_ifaceno = uaa->info.bIfaceNum;
422 
423 	mtx_init(&sc->sc_mutex, device_get_nameunit(dev), NULL, MTX_DEF);
424 
425 	/*
426 	 * Some MBIM hardware does not provide the mandatory CDC Union
427 	 * Descriptor, so we also look at matching Interface
428 	 * Association Descriptors to find out the MBIM Data Interface
429 	 * number.
430 	 */
431 	sc->sc_ver_maj = sc->sc_ver_min = -1;
432 	sc->sc_maxpktlen = MBIM_MAXSEGSZ_MINVAL;
433 	id = usbd_get_interface_descriptor(uaa->iface);
434 
435 	ud = usbd_find_descriptor(sc->sc_udev, id, uaa->info.bIfaceIndex,
436 			UDESC_CS_INTERFACE, 0xff, UDESCSUB_CDC_UNION, 0xff);
437 	if (ud != NULL) {
438 		data_ifaceno = ud->bSlaveInterface[0];
439 	}
440 
441 	md = usbd_find_descriptor(sc->sc_udev, id, uaa->info.bIfaceIndex,
442 			UDESC_CS_INTERFACE, 0xff, UDESCSUB_MBIM, 0xff);
443 	if (md != NULL) {
444 		v = UGETW(md->bcdMBIMVersion);
445 		sc->sc_ver_maj = MBIM_VER_MAJOR(v);
446 		sc->sc_ver_min = MBIM_VER_MINOR(v);
447 		sc->sc_ctrl_len = UGETW(md->wMaxControlMessage);
448 		/* Never trust a USB device! Could try to exploit us */
449 		if (sc->sc_ctrl_len < MBIM_CTRLMSG_MINLEN ||
450 				sc->sc_ctrl_len > MBIM_CTRLMSG_MAXLEN) {
451 			DPRINTF("control message len %d out of "
452 					"bounds [%d .. %d]\n",
453 					sc->sc_ctrl_len, MBIM_CTRLMSG_MINLEN,
454 					MBIM_CTRLMSG_MAXLEN);
455 			/* continue anyway */
456 		}
457 		sc->sc_maxpktlen = UGETW(md->wMaxSegmentSize);
458 		DPRINTFN(2, "ctrl_len=%d, maxpktlen=%d, cap=0x%x\n",
459 				sc->sc_ctrl_len, sc->sc_maxpktlen,
460 				md->bmNetworkCapabilities);
461 	}
462 	if (sc->sc_ver_maj < 0) {
463 		device_printf(dev, "error: missing MBIM descriptor\n");
464 		goto fail;
465 	}
466 
467 	device_printf(dev, "version %d.%d\n", sc->sc_ver_maj,
468 	    sc->sc_ver_min);
469 
470 	if (usbd_lookup_id_by_uaa(umb_fccauth_devs, sizeof (umb_fccauth_devs),
471 				  uaa)) {
472 		sc->sc_flags |= UMBFLG_FCC_AUTH_REQUIRED;
473 		sc->sc_cid = -1;
474 	}
475 
476 	for (i = 0; i < sc->sc_udev->ifaces_max; i++) {
477 		iface = usbd_get_iface(sc->sc_udev, i);
478 		id = usbd_get_interface_descriptor(iface);
479 		if (id == NULL)
480 			break;
481 
482 		if (id->bInterfaceNumber == data_ifaceno) {
483 			sc->sc_data_iface = iface;
484 			sc->sc_ifaces_index[0] = i;
485 			sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
486 			break;
487 		}
488 	}
489 	if (sc->sc_data_iface == NULL) {
490 		device_printf(dev, "error: no data interface found\n");
491 		goto fail;
492 	}
493 
494 	/*
495 	 * If this is a combined NCM/MBIM function, switch to
496 	 * alternate setting one to enable MBIM.
497 	 */
498 	id = usbd_get_interface_descriptor(uaa->iface);
499 	if (id != NULL && id->bInterfaceClass == UICLASS_CDC &&
500 	    id->bInterfaceSubClass == UISUBCLASS_NETWORK_CONTROL_MODEL) {
501 		device_printf(sc->sc_dev, "combined NCM/MBIM\n");
502 		error = usbd_req_set_alt_interface_no(sc->sc_udev,
503 				NULL, uaa->info.bIfaceIndex, 1);
504 		if (error != USB_ERR_NORMAL_COMPLETION) {
505 			device_printf(dev, "error: Could not switch to"
506 					   " alternate setting for MBIM\n");
507 			goto fail;
508 		}
509 		sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex + 1;
510 	}
511 
512 	if (usb_proc_create(&sc->sc_taskqueue, &sc->sc_mutex,
513 				device_get_nameunit(sc->sc_dev),
514 				USB_PRI_MED) != 0)
515 		goto fail;
516 
517 	DPRINTFN(2, "ctrl-ifno#%d: data-ifno#%d\n", sc->sc_ctrl_ifaceno,
518 	    data_ifaceno);
519 
520 	usb_callout_init_mtx(&sc->sc_statechg_timer, &sc->sc_mutex, 0);
521 
522 	umb_ncm_setup(sc, config);
523 	DPRINTFN(2, "%s: rx/tx size %d/%d\n", DEVNAM(sc),
524 			sc->sc_rx_bufsz, sc->sc_tx_bufsz);
525 
526 	sc->sc_rx_buf = malloc(sc->sc_rx_bufsz, M_DEVBUF, M_WAITOK);
527 	sc->sc_tx_buf = malloc(sc->sc_tx_bufsz, M_DEVBUF, M_WAITOK);
528 
529 	for (i = 0; i != 32; i++) {
530 		error = usbd_set_alt_interface_index(sc->sc_udev,
531 				sc->sc_ifaces_index[0], i);
532 		if (error)
533 			break;
534 
535 		error = usbd_transfer_setup(sc->sc_udev, sc->sc_ifaces_index,
536 				sc->sc_xfer, config, UMB_N_TRANSFER,
537 				sc, &sc->sc_mutex);
538 		if (error == USB_ERR_NORMAL_COMPLETION)
539 			break;
540 	}
541 	if (error || (i == 32)) {
542 		device_printf(sc->sc_dev, "error: failed to setup xfers\n");
543 		goto fail;
544 	}
545 
546 	sc->sc_resp_buf = malloc(sc->sc_ctrl_len, M_DEVBUF, M_WAITOK);
547 	sc->sc_ctrl_msg = malloc(sc->sc_ctrl_len, M_DEVBUF, M_WAITOK);
548 
549 	sc->sc_info.regstate = MBIM_REGSTATE_UNKNOWN;
550 	sc->sc_info.pin_attempts_left = UMB_VALUE_UNKNOWN;
551 	sc->sc_info.rssi = UMB_VALUE_UNKNOWN;
552 	sc->sc_info.ber = UMB_VALUE_UNKNOWN;
553 
554 	/* defer attaching the interface */
555 	mtx_lock(&sc->sc_mutex);
556 	umb_add_task(sc, umb_attach_task,
557 			&sc->sc_proc_attach_task[0].hdr,
558 			&sc->sc_proc_attach_task[1].hdr, 0);
559 	mtx_unlock(&sc->sc_mutex);
560 
561 	return (0);
562 
563 fail:
564 	umb_detach(sc->sc_dev);
565 	return (ENXIO);
566 }
567 
568 static void
umb_attach_task(struct usb_proc_msg * msg)569 umb_attach_task(struct usb_proc_msg *msg)
570 {
571 	struct umb_task *task = (struct umb_task *)msg;
572 	struct umb_softc *sc = task->sc;
573 	if_t ifp;
574 
575 	mtx_unlock(&sc->sc_mutex);
576 
577 	CURVNET_SET_QUIET(vnet0);
578 
579 	/* initialize the interface */
580 	sc->sc_if = ifp = if_alloc(IFT_MBIM);
581 	if_initname(ifp, "umb", device_get_unit(sc->sc_dev));
582 
583 	if_setsoftc(ifp, sc);
584 	if_setflags(ifp, IFF_SIMPLEX | IFF_MULTICAST | IFF_POINTOPOINT);
585 	if_setioctlfn(ifp, umb_ioctl);
586 	if_setinputfn(ifp, umb_input);
587 	if_setoutputfn(ifp, umb_output);
588 	if_setstartfn(ifp, umb_start);
589 	if_setinitfn(ifp, umb_init);
590 
591 #if 0
592 	if_setwatchdog(ifp, umb_watchdog);
593 #endif
594 	if_link_state_change(ifp, LINK_STATE_DOWN);
595 	ifmedia_init(&sc->sc_im, 0, umb_mediachange, umb_mediastatus);
596 	ifmedia_add(&sc->sc_im, IFM_NONE | IFM_AUTO, 0, NULL);
597 
598 	if_setifheaderlen(ifp, sizeof (struct ncm_header16) +
599 	    sizeof (struct ncm_pointer16)); /* XXX - IFAPI */
600 	/* XXX hard-coded atm */
601 	if_setmtu(ifp, MIN(2048, sc->sc_maxpktlen));
602 	if_setsendqlen(ifp, ifqmaxlen);
603 	if_setsendqready(ifp);
604 
605 	/* attach the interface */
606 	if_attach(ifp);
607 	bpfattach(ifp, DLT_RAW, 0);
608 
609 	sc->sc_attached = 1;
610 
611 	CURVNET_RESTORE();
612 
613 	umb_init(sc);
614 	mtx_lock(&sc->sc_mutex);
615 }
616 
617 static int
umb_detach(device_t dev)618 umb_detach(device_t dev)
619 {
620 	struct umb_softc *sc = device_get_softc(dev);
621 	if_t ifp = GET_IFP(sc);
622 
623 	usb_proc_drain(&sc->sc_taskqueue);
624 
625 	mtx_lock(&sc->sc_mutex);
626 	if (ifp != NULL && (if_getdrvflags(ifp) & IFF_DRV_RUNNING))
627 		umb_down(sc, 1);
628 	umb_close(sc);
629 	mtx_unlock(&sc->sc_mutex);
630 
631 	usbd_transfer_unsetup(sc->sc_xfer, UMB_N_TRANSFER);
632 
633 	free(sc->sc_tx_buf, M_DEVBUF);
634 	free(sc->sc_rx_buf, M_DEVBUF);
635 
636 	usb_callout_drain(&sc->sc_statechg_timer);
637 
638 	usb_proc_free(&sc->sc_taskqueue);
639 
640 	mtx_destroy(&sc->sc_mutex);
641 
642 	free(sc->sc_ctrl_msg, M_DEVBUF);
643 	free(sc->sc_resp_buf, M_DEVBUF);
644 
645 	if (ifp != NULL && if_getsoftc(ifp)) {
646 		ifmedia_removeall(&sc->sc_im);
647 	}
648 	if (sc->sc_attached) {
649 		bpfdetach(ifp);
650 		if_detach(ifp);
651 		if_free(ifp);
652 		sc->sc_if = NULL;
653 	}
654 
655 	return 0;
656 }
657 
658 static void
umb_ncm_setup(struct umb_softc * sc,struct usb_config * config)659 umb_ncm_setup(struct umb_softc *sc, struct usb_config * config)
660 {
661 	usb_device_request_t req;
662 	struct ncm_ntb_parameters np;
663 	usb_error_t error;
664 
665 	/* Query NTB transfers sizes */
666 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
667 	req.bRequest = NCM_GET_NTB_PARAMETERS;
668 	USETW(req.wValue, 0);
669 	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
670 	USETW(req.wLength, sizeof (np));
671 	mtx_lock(&sc->sc_mutex);
672 	error = usbd_do_request(sc->sc_udev, &sc->sc_mutex, &req, &np);
673 	mtx_unlock(&sc->sc_mutex);
674 	if (error == USB_ERR_NORMAL_COMPLETION &&
675 	    UGETW(np.wLength) == sizeof (np)) {
676 		config[UMB_BULK_RX].bufsize = UGETDW(np.dwNtbInMaxSize);
677 		config[UMB_BULK_TX].bufsize = UGETDW(np.dwNtbOutMaxSize);
678 	}
679 	sc->sc_rx_bufsz = config[UMB_BULK_RX].bufsize;
680 	sc->sc_tx_bufsz = config[UMB_BULK_TX].bufsize;
681 }
682 
683 static int
umb_handle_request(device_t dev,const void * preq,void ** pptr,uint16_t * plen,uint16_t offset,uint8_t * pstate)684 umb_handle_request(device_t dev,
685     const void *preq, void **pptr, uint16_t *plen,
686     uint16_t offset, uint8_t *pstate)
687 {
688 	/* FIXME really implement */
689 
690 	return (ENXIO);
691 }
692 
693 static int
umb_suspend(device_t dev)694 umb_suspend(device_t dev)
695 {
696 	device_printf(dev, "Suspending\n");
697 	return (0);
698 }
699 
700 static int
umb_resume(device_t dev)701 umb_resume(device_t dev)
702 {
703 	device_printf(dev, "Resuming\n");
704 	return (0);
705 }
706 
707 static int
umb_deactivate(device_t dev)708 umb_deactivate(device_t dev)
709 {
710 	struct umb_softc *sc = device_get_softc(dev);
711 	if_t ifp = GET_IFP(sc);
712 
713 	if (ifp != NULL) {
714 		if_dead(ifp);
715 	}
716 	sc->sc_dying = 1;
717 	return 0;
718 }
719 
720 static void
umb_close_bulkpipes(struct umb_softc * sc)721 umb_close_bulkpipes(struct umb_softc *sc)
722 {
723 	if_t ifp = GET_IFP(sc);
724 
725 	if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE));
726 
727 	umb_rxflush(sc);
728 	umb_txflush(sc);
729 
730 	usbd_transfer_stop(sc->sc_xfer[UMB_BULK_RX]);
731 	usbd_transfer_stop(sc->sc_xfer[UMB_BULK_TX]);
732 }
733 
734 static int
umb_ioctl(if_t ifp,u_long cmd,caddr_t data)735 umb_ioctl(if_t ifp, u_long cmd, caddr_t data)
736 {
737 	struct umb_softc *sc = if_getsoftc(ifp);
738 	struct in_ifaddr *ia = (struct in_ifaddr *)data;
739 	struct ifreq *ifr = (struct ifreq *)data;
740 	int error = 0;
741 	struct umb_parameter mp;
742 
743 	if (sc->sc_dying)
744 		return EIO;
745 
746 	switch (cmd) {
747 	case SIOCSIFADDR:
748 		switch (ia->ia_ifa.ifa_addr->sa_family) {
749 		case AF_INET:
750 			break;
751 #ifdef INET6
752 		case AF_INET6:
753 			break;
754 #endif /* INET6 */
755 		default:
756 			error = EAFNOSUPPORT;
757 			break;
758 		}
759 		break;
760 	case SIOCSIFFLAGS:
761 		mtx_lock(&sc->sc_mutex);
762 		umb_add_task(sc, umb_state_task,
763 				&sc->sc_proc_state_task[0].hdr,
764 				&sc->sc_proc_state_task[1].hdr, 1);
765 		mtx_unlock(&sc->sc_mutex);
766 		break;
767 	case SIOCGUMBINFO:
768 		error = copyout(&sc->sc_info, ifr->ifr_ifru.ifru_data,
769 		    sizeof (sc->sc_info));
770 		break;
771 	case SIOCSUMBPARAM:
772 		error = priv_check(curthread, PRIV_NET_SETIFPHYS);
773 		if (error)
774 			break;
775 
776 		if ((error = copyin(ifr->ifr_ifru.ifru_data, &mp, sizeof (mp))) != 0)
777 			break;
778 
779 		if ((error = umb_setpin(sc, mp.op, mp.is_puk, mp.pin, mp.pinlen,
780 		    mp.newpin, mp.newpinlen)) != 0)
781 			break;
782 
783 		if (mp.apnlen < 0 || mp.apnlen > sizeof (sc->sc_info.apn)) {
784 			error = EINVAL;
785 			break;
786 		}
787 		sc->sc_roaming = mp.roaming ? 1 : 0;
788 		memset(sc->sc_info.apn, 0, sizeof (sc->sc_info.apn));
789 		memcpy(sc->sc_info.apn, mp.apn, mp.apnlen);
790 		sc->sc_info.apnlen = mp.apnlen;
791 		memset(sc->sc_info.username, 0, sizeof (sc->sc_info.username));
792 		memcpy(sc->sc_info.username, mp.username, mp.usernamelen);
793 		sc->sc_info.usernamelen = mp.usernamelen;
794 		memset(sc->sc_info.password, 0, sizeof (sc->sc_info.password));
795 		memcpy(sc->sc_info.password, mp.password, mp.passwordlen);
796 		sc->sc_info.passwordlen = mp.passwordlen;
797 		sc->sc_info.preferredclasses = mp.preferredclasses;
798 		umb_setdataclass(sc);
799 		break;
800 	case SIOCGUMBPARAM:
801 		memset(&mp, 0, sizeof (mp));
802 		memcpy(mp.apn, sc->sc_info.apn, sc->sc_info.apnlen);
803 		mp.apnlen = sc->sc_info.apnlen;
804 		mp.roaming = sc->sc_roaming;
805 		mp.preferredclasses = sc->sc_info.preferredclasses;
806 		error = copyout(&mp, ifr->ifr_ifru.ifru_data, sizeof (mp));
807 		break;
808 	case SIOCSIFMTU:
809 		/* Does this include the NCM headers and tail? */
810 		if (ifr->ifr_mtu > if_getmtu(ifp)) {
811 			error = EINVAL;
812 			break;
813 		}
814 		if_setmtu(ifp, ifr->ifr_mtu);
815 		break;
816 	case SIOCAIFADDR:
817 	case SIOCSIFDSTADDR:
818 	case SIOCADDMULTI:
819 	case SIOCDELMULTI:
820 		break;
821 	case SIOCGIFMEDIA:
822 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_im, cmd);
823 		break;
824 	default:
825 		error = EINVAL;
826 		break;
827 	}
828 	return (error);
829 }
830 
831 static void
umb_init(void * arg)832 umb_init(void *arg)
833 {
834 	struct umb_softc *sc = arg;
835 
836 	mtx_lock(&sc->sc_mutex);
837 	umb_add_task(sc, umb_start_task,
838 			&sc->sc_proc_start_task[0].hdr,
839 			&sc->sc_proc_start_task[1].hdr, 0);
840 	mtx_unlock(&sc->sc_mutex);
841 }
842 
843 static void
umb_input(if_t ifp,struct mbuf * m)844 umb_input(if_t ifp, struct mbuf *m)
845 {
846 	struct mbuf *mn;
847 	struct epoch_tracker et;
848 
849 	while (m) {
850 		mn = m->m_nextpkt;
851 		m->m_nextpkt = NULL;
852 
853 		NET_EPOCH_ENTER(et);
854 		BPF_MTAP(ifp, m);
855 
856 		CURVNET_SET_QUIET(if_getvnet(ifp));
857 
858 		netisr_dispatch(NETISR_IP, m);
859 		m = mn;
860 
861 		CURVNET_RESTORE();
862 		NET_EPOCH_EXIT(et);
863 	}
864 }
865 
866 static int
umb_output(if_t ifp,struct mbuf * m,const struct sockaddr * dst,struct route * rtp)867 umb_output(if_t ifp, struct mbuf *m, const struct sockaddr *dst,
868     struct route *rtp)
869 {
870 	int error;
871 
872 	DPRINTFN(10, "%s: enter\n", __func__);
873 
874 	switch (dst->sa_family) {
875 #ifdef INET6
876 	case AF_INET6:
877 		/* fall through */
878 #endif
879 	case AF_INET:
880 		break;
881 
882 		/* silently drop dhclient packets */
883 	case AF_UNSPEC:
884 		m_freem(m);
885 		return (0);
886 
887 		/* drop other packet types */
888 	default:
889 		m_freem(m);
890 		return (EAFNOSUPPORT);
891 	}
892 
893 	/*
894 	 * Queue message on interface, and start output if interface
895 	 * not yet active.
896 	 */
897 	error = if_transmit(ifp, m);
898 	if (error) {
899 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
900 		return (ENOBUFS);
901 	}
902 
903 	return (0);
904 }
905 
906 static void
umb_start(if_t ifp)907 umb_start(if_t ifp)
908 {
909 	struct umb_softc *sc = if_getsoftc(ifp);
910 
911 	if (sc->sc_dying || !(if_getdrvflags(ifp) & IFF_DRV_RUNNING))
912 		return;
913 
914 	mtx_lock(&sc->sc_mutex);
915 	usbd_transfer_start(sc->sc_xfer[UMB_BULK_TX]);
916 	mtx_unlock(&sc->sc_mutex);
917 }
918 
919 static void
umb_start_task(struct usb_proc_msg * msg)920 umb_start_task(struct usb_proc_msg *msg)
921 {
922 	struct umb_task *task = (struct umb_task *)msg;
923 	struct umb_softc *sc = task->sc;
924 	if_t ifp = GET_IFP(sc);
925 
926 	DPRINTF("%s()\n", __func__);
927 
928 	mtx_assert(&sc->sc_mutex, MA_OWNED);
929 
930 	if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0);
931 
932 	/* start interrupt transfer */
933 	usbd_transfer_start(sc->sc_xfer[UMB_INTR_RX]);
934 
935 	umb_open(sc);
936 }
937 
938 #if 0
939 static void
940 umb_watchdog(if_t ifp)
941 {
942 	struct umb_softc *sc = if_getsoftc(ifp);
943 
944 	if (sc->sc_dying)
945 		return;
946 
947 	if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
948 	device_printf(sc->sc_dev, "watchdog timeout\n");
949 	usbd_transfer_drain(sc->sc_xfer[UMB_BULK_TX]);
950 	return;
951 }
952 #endif
953 
954 static void
umb_statechg_timeout(void * arg)955 umb_statechg_timeout(void *arg)
956 {
957 	struct umb_softc *sc = arg;
958 	if_t ifp = GET_IFP(sc);
959 
960 	mtx_assert(&sc->sc_mutex, MA_OWNED);
961 
962 	if (sc->sc_info.regstate != MBIM_REGSTATE_ROAMING || sc->sc_roaming)
963 		if (if_getflags(ifp) & IFF_DEBUG)
964 			log(LOG_DEBUG, "%s: state change timeout\n",
965 					DEVNAM(sc));
966 
967 	umb_add_task(sc, umb_state_task,
968 			&sc->sc_proc_state_task[0].hdr,
969 			&sc->sc_proc_state_task[1].hdr, 0);
970 }
971 
972 static int
umb_mediachange(if_t ifp)973 umb_mediachange(if_t  ifp)
974 {
975 	return 0;
976 }
977 
978 static void
umb_mediastatus(if_t ifp,struct ifmediareq * imr)979 umb_mediastatus(if_t  ifp, struct ifmediareq * imr)
980 {
981 	switch (if_getlinkstate(ifp)) {
982 	case LINK_STATE_UP:
983 		imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
984 		break;
985 	case LINK_STATE_DOWN:
986 		imr->ifm_status = IFM_AVALID;
987 		break;
988 	default:
989 		imr->ifm_status = 0;
990 		break;
991 	}
992 }
993 
994 static void
umb_add_task(struct umb_softc * sc,usb_proc_callback_t callback,struct usb_proc_msg * t0,struct usb_proc_msg * t1,int sync)995 umb_add_task(struct umb_softc *sc, usb_proc_callback_t callback,
996 		struct usb_proc_msg *t0, struct usb_proc_msg *t1, int sync)
997 {
998 	struct umb_task * task;
999 
1000 	mtx_assert(&sc->sc_mutex, MA_OWNED);
1001 
1002 	if (usb_proc_is_gone(&sc->sc_taskqueue)) {
1003 		return;
1004 	}
1005 
1006 	task = usb_proc_msignal(&sc->sc_taskqueue, t0, t1);
1007 
1008 	task->hdr.pm_callback = callback;
1009 	task->sc = sc;
1010 
1011 	if (sync) {
1012 		usb_proc_mwait(&sc->sc_taskqueue, t0, t1);
1013 	}
1014 }
1015 
1016 static void
umb_newstate(struct umb_softc * sc,enum umb_state newstate,int flags)1017 umb_newstate(struct umb_softc *sc, enum umb_state newstate, int flags)
1018 {
1019 	if_t ifp = GET_IFP(sc);
1020 
1021 	if (newstate == sc->sc_state)
1022 		return;
1023 	if (((flags & UMB_NS_DONT_DROP) && newstate < sc->sc_state) ||
1024 	    ((flags & UMB_NS_DONT_RAISE) && newstate > sc->sc_state))
1025 		return;
1026 	if (if_getflags(ifp) & IFF_DEBUG)
1027 		log(LOG_DEBUG, "%s: state going %s from '%s' to '%s'\n",
1028 		    DEVNAM(sc), newstate > sc->sc_state ? "up" : "down",
1029 		    umb_istate(sc->sc_state), umb_istate(newstate));
1030 	sc->sc_state = newstate;
1031 	umb_add_task(sc, umb_state_task,
1032 			&sc->sc_proc_state_task[0].hdr,
1033 			&sc->sc_proc_state_task[1].hdr, 0);
1034 }
1035 
1036 static void
umb_state_task(struct usb_proc_msg * msg)1037 umb_state_task(struct usb_proc_msg *msg)
1038 {
1039 	struct umb_task *task = (struct umb_task *)msg;
1040 	struct umb_softc *sc = task->sc;
1041 	if_t ifp = GET_IFP(sc);
1042 	struct ifreq ifr;
1043 	int	 state;
1044 
1045 	DPRINTF("%s()\n", __func__);
1046 
1047 	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
1048 		/*
1049 		 * Query the registration state until we're with the home
1050 		 * network again.
1051 		 */
1052 		umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY, NULL, 0);
1053 		return;
1054 	}
1055 
1056 	if (if_getflags(ifp) & IFF_UP)
1057 		umb_up(sc);
1058 	else
1059 		umb_down(sc, 0);
1060 
1061 	state = (sc->sc_state == UMB_S_UP) ? LINK_STATE_UP : LINK_STATE_DOWN;
1062 	if (if_getlinkstate(ifp) != state) {
1063 		if (if_getflags(ifp) & IFF_DEBUG)
1064 			log(LOG_DEBUG, "%s: link state changed from %s to %s\n",
1065 			    DEVNAM(sc),
1066 			    (if_getlinkstate(ifp) == LINK_STATE_UP)
1067 			    ? "up" : "down",
1068 			    (state == LINK_STATE_UP) ? "up" : "down");
1069 		if_link_state_change(ifp, state); /* XXX - IFAPI */
1070 		if (state != LINK_STATE_UP) {
1071 			/*
1072 			 * Purge any existing addresses
1073 			 */
1074 			memset(sc->sc_info.ipv4dns, 0,
1075 			    sizeof (sc->sc_info.ipv4dns));
1076 			mtx_unlock(&sc->sc_mutex);
1077 			CURVNET_SET_QUIET(if_getvnet(ifp));
1078 			if (in_control(NULL, SIOCGIFADDR, (caddr_t)&ifr, ifp,
1079 				       curthread) == 0 &&
1080 			    satosin(&ifr.ifr_addr)->sin_addr.s_addr !=
1081 			    INADDR_ANY) {
1082 				in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr,
1083 					   ifp, curthread);
1084 			}
1085 			CURVNET_RESTORE();
1086 			mtx_lock(&sc->sc_mutex);
1087 		}
1088 		if_link_state_change(ifp, state);
1089 	}
1090 }
1091 
1092 static void
umb_up(struct umb_softc * sc)1093 umb_up(struct umb_softc *sc)
1094 {
1095 	if_t ifp = GET_IFP(sc);
1096 
1097 	switch (sc->sc_state) {
1098 	case UMB_S_DOWN:
1099 		DPRINTF("init: opening ...\n");
1100 		umb_open(sc);
1101 		break;
1102 	case UMB_S_OPEN:
1103 		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED) {
1104 			if (sc->sc_cid == -1) {
1105 				DPRINTF("init: allocating CID ...\n");
1106 				umb_allocate_cid(sc);
1107 				break;
1108 			} else
1109 				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
1110 		} else {
1111 			DPRINTF("init: turning radio on ...\n");
1112 			umb_radio(sc, 1);
1113 			break;
1114 		}
1115 		/*FALLTHROUGH*/
1116 	case UMB_S_CID:
1117 		DPRINTF("init: sending FCC auth ...\n");
1118 		umb_send_fcc_auth(sc);
1119 		break;
1120 	case UMB_S_RADIO:
1121 		DPRINTF("init: checking SIM state ...\n");
1122 		umb_cmd(sc, MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CMDOP_QRY,
1123 		    NULL, 0);
1124 		break;
1125 	case UMB_S_SIMREADY:
1126 		DPRINTF("init: attaching ...\n");
1127 		umb_packet_service(sc, 1);
1128 		break;
1129 	case UMB_S_ATTACHED:
1130 		sc->sc_tx_seq = 0;
1131 		DPRINTF("init: connecting ...\n");
1132 		umb_connect(sc);
1133 		break;
1134 	case UMB_S_CONNECTED:
1135 		DPRINTF("init: getting IP config ...\n");
1136 		umb_qry_ipconfig(sc);
1137 		break;
1138 	case UMB_S_UP:
1139 		DPRINTF("init: reached state UP\n");
1140 		if (!(if_getflags(ifp) & IFF_DRV_RUNNING)) {
1141 			if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0);
1142 			if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
1143 			umb_rx(sc);
1144 		}
1145 		break;
1146 	}
1147 	if (sc->sc_state < UMB_S_UP)
1148 		usb_callout_reset(&sc->sc_statechg_timer,
1149 		    UMB_STATE_CHANGE_TIMEOUT * hz, umb_statechg_timeout, sc);
1150 	else {
1151 		usb_callout_stop(&sc->sc_statechg_timer);
1152 	}
1153 	return;
1154 }
1155 
1156 static void
umb_down(struct umb_softc * sc,int force)1157 umb_down(struct umb_softc *sc, int force)
1158 {
1159 	umb_close_bulkpipes(sc);
1160 
1161 	switch (sc->sc_state) {
1162 	case UMB_S_UP:
1163 	case UMB_S_CONNECTED:
1164 		DPRINTF("stop: disconnecting ...\n");
1165 		umb_disconnect(sc);
1166 		if (!force)
1167 			break;
1168 		/*FALLTHROUGH*/
1169 	case UMB_S_ATTACHED:
1170 		DPRINTF("stop: detaching ...\n");
1171 		umb_packet_service(sc, 0);
1172 		if (!force)
1173 			break;
1174 		/*FALLTHROUGH*/
1175 	case UMB_S_SIMREADY:
1176 	case UMB_S_RADIO:
1177 		DPRINTF("stop: turning radio off ...\n");
1178 		umb_radio(sc, 0);
1179 		if (!force)
1180 			break;
1181 		/*FALLTHROUGH*/
1182 	case UMB_S_CID:
1183 	case UMB_S_OPEN:
1184 	case UMB_S_DOWN:
1185 		/* Do not close the device */
1186 		DPRINTF("stop: reached state DOWN\n");
1187 		break;
1188 	}
1189 	if (force)
1190 		sc->sc_state = UMB_S_OPEN;
1191 
1192 	if (sc->sc_state > UMB_S_OPEN)
1193 		usb_callout_reset(&sc->sc_statechg_timer,
1194 		    UMB_STATE_CHANGE_TIMEOUT * hz, umb_statechg_timeout, sc);
1195 	else
1196 		usb_callout_stop(&sc->sc_statechg_timer);
1197 }
1198 
1199 static void
umb_get_response_task(struct usb_proc_msg * msg)1200 umb_get_response_task(struct usb_proc_msg *msg)
1201 {
1202 	struct umb_task *task = (struct umb_task *)msg;
1203 	struct umb_softc *sc = task->sc;
1204 	int	 len;
1205 
1206 	DPRINTF("%s()\n", __func__);
1207 	/*
1208 	 * Function is required to send on RESPONSE_AVAILABLE notification for
1209 	 * each encapsulated response that is to be processed by the host.
1210 	 * But of course, we can receive multiple notifications before the
1211 	 * response task is run.
1212 	 */
1213 	while (sc->sc_nresp > 0) {
1214 		--sc->sc_nresp;
1215 		len = sc->sc_ctrl_len;
1216 		if (umb_get_encap_response(sc, sc->sc_resp_buf, &len))
1217 			umb_decode_response(sc, sc->sc_resp_buf, len);
1218 	}
1219 }
1220 
1221 static void
umb_decode_response(struct umb_softc * sc,void * response,int len)1222 umb_decode_response(struct umb_softc *sc, void *response, int len)
1223 {
1224 	struct mbim_msghdr *hdr = response;
1225 	struct mbim_fragmented_msg_hdr *fraghdr;
1226 	uint32_t type;
1227 
1228 	DPRINTFN(3, "got response: len %d\n", len);
1229 	DDUMPN(4, response, len);
1230 
1231 	if (len < sizeof (*hdr) || le32toh(hdr->len) != len) {
1232 		/*
1233 		 * We should probably cancel a transaction, but since the
1234 		 * message is too short, we cannot decode the transaction
1235 		 * id (tid) and hence don't know, whom to cancel. Must wait
1236 		 * for the timeout.
1237 		 */
1238 		DPRINTF("received short response (len %d)\n",
1239 		    len);
1240 		return;
1241 	}
1242 
1243 	/*
1244 	 * XXX FIXME: if message is fragmented, store it until last frag
1245 	 *	is received and then re-assemble all fragments.
1246 	 */
1247 	type = le32toh(hdr->type);
1248 	switch (type) {
1249 	case MBIM_INDICATE_STATUS_MSG:
1250 	case MBIM_COMMAND_DONE:
1251 		fraghdr = response;
1252 		if (le32toh(fraghdr->frag.nfrag) != 1) {
1253 			DPRINTF("discarding fragmented messages\n");
1254 			return;
1255 		}
1256 		break;
1257 	default:
1258 		break;
1259 	}
1260 
1261 	DPRINTF("<- rcv %s (tid %u)\n", umb_request2str(type),
1262 	    le32toh(hdr->tid));
1263 	switch (type) {
1264 	case MBIM_FUNCTION_ERROR_MSG:
1265 	case MBIM_HOST_ERROR_MSG:
1266 	{
1267 		struct mbim_f2h_hosterr *e;
1268 		int	 err;
1269 
1270 		if (len >= sizeof (*e)) {
1271 			e = response;
1272 			err = le32toh(e->err);
1273 
1274 			DPRINTF("%s message, error %s (tid %u)\n",
1275 			    umb_request2str(type),
1276 			    umb_error2str(err), le32toh(hdr->tid));
1277 			if (err == MBIM_ERROR_NOT_OPENED)
1278 				umb_newstate(sc, UMB_S_DOWN, 0);
1279 		}
1280 		break;
1281 	}
1282 	case MBIM_INDICATE_STATUS_MSG:
1283 		umb_handle_indicate_status_msg(sc, response, len);
1284 		break;
1285 	case MBIM_OPEN_DONE:
1286 		umb_handle_opendone_msg(sc, response, len);
1287 		break;
1288 	case MBIM_CLOSE_DONE:
1289 		umb_handle_closedone_msg(sc, response, len);
1290 		break;
1291 	case MBIM_COMMAND_DONE:
1292 		umb_command_done(sc, response, len);
1293 		break;
1294 	default:
1295 		DPRINTF("discard message %s\n",
1296 		    umb_request2str(type));
1297 		break;
1298 	}
1299 }
1300 
1301 static void
umb_handle_indicate_status_msg(struct umb_softc * sc,void * data,int len)1302 umb_handle_indicate_status_msg(struct umb_softc *sc, void *data, int len)
1303 {
1304 	struct mbim_f2h_indicate_status *m = data;
1305 	uint32_t infolen;
1306 	uint32_t cid;
1307 
1308 	if (len < sizeof (*m)) {
1309 		DPRINTF("discard short %s message\n",
1310 		    umb_request2str(le32toh(m->hdr.type)));
1311 		return;
1312 	}
1313 	if (memcmp(m->devid, umb_uuid_basic_connect, sizeof (m->devid))) {
1314 		DPRINTF("discard %s message for other UUID '%s'\n",
1315 		    umb_request2str(le32toh(m->hdr.type)),
1316 		    umb_uuid2str(m->devid));
1317 		return;
1318 	}
1319 	infolen = le32toh(m->infolen);
1320 	if (len < sizeof (*m) + infolen) {
1321 		DPRINTF("discard truncated %s message (want %d, got %d)\n",
1322 		    umb_request2str(le32toh(m->hdr.type)),
1323 		    (int)sizeof (*m) + infolen, len);
1324 		return;
1325 	}
1326 
1327 	cid = le32toh(m->cid);
1328 	DPRINTF("indicate %s status\n", umb_cid2str(cid));
1329 	umb_decode_cid(sc, cid, m->info, infolen);
1330 }
1331 
1332 static void
umb_handle_opendone_msg(struct umb_softc * sc,void * data,int len)1333 umb_handle_opendone_msg(struct umb_softc *sc, void *data, int len)
1334 {
1335 	struct mbim_f2h_openclosedone *resp = data;
1336 	if_t ifp = GET_IFP(sc);
1337 	uint32_t status;
1338 
1339 	status = le32toh(resp->status);
1340 	if (status == MBIM_STATUS_SUCCESS) {
1341 		if (sc->sc_maxsessions == 0) {
1342 			umb_cmd(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_QRY, NULL,
1343 			    0);
1344 			umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_QRY, NULL, 0);
1345 			umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY,
1346 			    NULL, 0);
1347 		}
1348 		umb_newstate(sc, UMB_S_OPEN, UMB_NS_DONT_DROP);
1349 	} else if (if_getflags(ifp) & IFF_DEBUG)
1350 		log(LOG_ERR, "%s: open error: %s\n", DEVNAM(sc),
1351 		    umb_status2str(status));
1352 	return;
1353 }
1354 
1355 static void
umb_handle_closedone_msg(struct umb_softc * sc,void * data,int len)1356 umb_handle_closedone_msg(struct umb_softc *sc, void *data, int len)
1357 {
1358 	struct mbim_f2h_openclosedone *resp = data;
1359 	uint32_t status;
1360 
1361 	status = le32toh(resp->status);
1362 	if (status == MBIM_STATUS_SUCCESS)
1363 		umb_newstate(sc, UMB_S_DOWN, 0);
1364 	else
1365 		DPRINTF("close error: %s\n",
1366 		    umb_status2str(status));
1367 	return;
1368 }
1369 
1370 static inline void
umb_getinfobuf(char * in,int inlen,uint32_t offs,uint32_t sz,void * out,size_t outlen)1371 umb_getinfobuf(char *in, int inlen, uint32_t offs, uint32_t sz,
1372     void *out, size_t outlen)
1373 {
1374 	offs = le32toh(offs);
1375 	sz = le32toh(sz);
1376 	memset(out, 0, outlen);
1377 	if ((uint64_t)inlen >= (uint64_t)offs + (uint64_t)sz)
1378 		memcpy(out, in + offs, MIN(sz, outlen));
1379 }
1380 
1381 static inline int
umb_padding(void * data,int len,size_t sz)1382 umb_padding(void *data, int len, size_t sz)
1383 {
1384 	char *p = data;
1385 	int np = 0;
1386 
1387 	while (len < sz && (len % 4) != 0) {
1388 		*p++ = '\0';
1389 		len++;
1390 		np++;
1391 	}
1392 	return np;
1393 }
1394 
1395 static inline int
umb_addstr(void * buf,size_t bufsz,int * offs,void * str,int slen,uint32_t * offsmember,uint32_t * sizemember)1396 umb_addstr(void *buf, size_t bufsz, int *offs, void *str, int slen,
1397     uint32_t *offsmember, uint32_t *sizemember)
1398 {
1399 	if (*offs + slen > bufsz)
1400 		return 0;
1401 
1402 	*sizemember = htole32((uint32_t)slen);
1403 	if (slen && str) {
1404 		*offsmember = htole32((uint32_t)*offs);
1405 		memcpy((char *)buf + *offs, str, slen);
1406 		*offs += slen;
1407 		*offs += umb_padding(buf, *offs, bufsz);
1408 	} else
1409 		*offsmember = htole32(0);
1410 	return 1;
1411 }
1412 
1413 static void
umb_in_len2mask(struct in_addr * mask,int len)1414 umb_in_len2mask(struct in_addr *mask, int len)
1415 {
1416 	int i;
1417 	u_char *p;
1418 
1419 	p = (u_char *)mask;
1420 	memset(mask, 0, sizeof (*mask));
1421 	for (i = 0; i < len / 8; i++)
1422 		p[i] = 0xff;
1423 	if (len % 8)
1424 		p[i] = (0xff00 >> (len % 8)) & 0xff;
1425 }
1426 
1427 static int
umb_decode_register_state(struct umb_softc * sc,void * data,int len)1428 umb_decode_register_state(struct umb_softc *sc, void *data, int len)
1429 {
1430 	struct mbim_cid_registration_state_info *rs = data;
1431 	if_t ifp = GET_IFP(sc);
1432 
1433 	if (len < sizeof (*rs))
1434 		return 0;
1435 	sc->sc_info.nwerror = le32toh(rs->nwerror);
1436 	sc->sc_info.regstate = le32toh(rs->regstate);
1437 	sc->sc_info.regmode = le32toh(rs->regmode);
1438 	sc->sc_info.cellclass = le32toh(rs->curcellclass);
1439 
1440 	/* XXX should we remember the provider_id? */
1441 	umb_getinfobuf(data, len, rs->provname_offs, rs->provname_size,
1442 	    sc->sc_info.provider, sizeof (sc->sc_info.provider));
1443 	umb_getinfobuf(data, len, rs->roamingtxt_offs, rs->roamingtxt_size,
1444 	    sc->sc_info.roamingtxt, sizeof (sc->sc_info.roamingtxt));
1445 
1446 	DPRINTFN(2, "%s, availclass 0x%x, class 0x%x, regmode %d\n",
1447 	    umb_regstate(sc->sc_info.regstate),
1448 	    le32toh(rs->availclasses), sc->sc_info.cellclass,
1449 	    sc->sc_info.regmode);
1450 
1451 	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING &&
1452 	    !sc->sc_roaming &&
1453 	    sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED) {
1454 		if (if_getflags(ifp) & IFF_DEBUG)
1455 			log(LOG_INFO,
1456 			    "%s: disconnecting from roaming network\n",
1457 			    DEVNAM(sc));
1458 		umb_disconnect(sc);
1459 	}
1460 	return 1;
1461 }
1462 
1463 static int
umb_decode_devices_caps(struct umb_softc * sc,void * data,int len)1464 umb_decode_devices_caps(struct umb_softc *sc, void *data, int len)
1465 {
1466 	struct mbim_cid_device_caps *dc = data;
1467 
1468 	if (len < sizeof (*dc))
1469 		return 0;
1470 	sc->sc_maxsessions = le32toh(dc->max_sessions);
1471 	sc->sc_info.supportedclasses = le32toh(dc->dataclass);
1472 	umb_getinfobuf(data, len, dc->devid_offs, dc->devid_size,
1473 	    sc->sc_info.devid, sizeof (sc->sc_info.devid));
1474 	umb_getinfobuf(data, len, dc->fwinfo_offs, dc->fwinfo_size,
1475 	    sc->sc_info.fwinfo, sizeof (sc->sc_info.fwinfo));
1476 	umb_getinfobuf(data, len, dc->hwinfo_offs, dc->hwinfo_size,
1477 	    sc->sc_info.hwinfo, sizeof (sc->sc_info.hwinfo));
1478 	DPRINTFN(2, "max sessions %d, supported classes 0x%x\n",
1479 	    sc->sc_maxsessions, sc->sc_info.supportedclasses);
1480 	return 1;
1481 }
1482 
1483 static int
umb_decode_subscriber_status(struct umb_softc * sc,void * data,int len)1484 umb_decode_subscriber_status(struct umb_softc *sc, void *data, int len)
1485 {
1486 	struct mbim_cid_subscriber_ready_info *si = data;
1487 	if_t ifp = GET_IFP(sc);
1488 	int	npn;
1489 
1490 	if (len < sizeof (*si))
1491 		return 0;
1492 	sc->sc_info.sim_state = le32toh(si->ready);
1493 
1494 	umb_getinfobuf(data, len, si->sid_offs, si->sid_size,
1495 	    sc->sc_info.sid, sizeof (sc->sc_info.sid));
1496 	umb_getinfobuf(data, len, si->icc_offs, si->icc_size,
1497 	    sc->sc_info.iccid, sizeof (sc->sc_info.iccid));
1498 
1499 	npn = le32toh(si->no_pn);
1500 	if (npn > 0)
1501 		umb_getinfobuf(data, len, si->pn[0].offs, si->pn[0].size,
1502 		    sc->sc_info.pn, sizeof (sc->sc_info.pn));
1503 	else
1504 		memset(sc->sc_info.pn, 0, sizeof (sc->sc_info.pn));
1505 
1506 	if (sc->sc_info.sim_state == MBIM_SIMSTATE_LOCKED)
1507 		sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1508 	if (if_getflags(ifp) & IFF_DEBUG)
1509 		log(LOG_INFO, "%s: SIM %s\n", DEVNAM(sc),
1510 		    umb_simstate(sc->sc_info.sim_state));
1511 	if (sc->sc_info.sim_state == MBIM_SIMSTATE_INITIALIZED)
1512 		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_DROP);
1513 	return 1;
1514 }
1515 
1516 static int
umb_decode_radio_state(struct umb_softc * sc,void * data,int len)1517 umb_decode_radio_state(struct umb_softc *sc, void *data, int len)
1518 {
1519 	struct mbim_cid_radio_state_info *rs = data;
1520 	if_t ifp = GET_IFP(sc);
1521 
1522 	if (len < sizeof (*rs))
1523 		return 0;
1524 
1525 	sc->sc_info.hw_radio_on =
1526 	    (le32toh(rs->hw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1527 	sc->sc_info.sw_radio_on =
1528 	    (le32toh(rs->sw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1529 	if (!sc->sc_info.hw_radio_on) {
1530 		device_printf(sc->sc_dev, "radio is disabled by hardware switch\n");
1531 		/*
1532 		 * XXX do we need a time to poll the state of the rfkill switch
1533 		 *	or will the device send an unsolicited notification
1534 		 *	in case the state changes?
1535 		 */
1536 		umb_newstate(sc, UMB_S_OPEN, 0);
1537 	} else if (!sc->sc_info.sw_radio_on) {
1538 		if (if_getflags(ifp) & IFF_DEBUG)
1539 			log(LOG_INFO, "%s: radio is off\n", DEVNAM(sc));
1540 		umb_newstate(sc, UMB_S_OPEN, 0);
1541 	} else
1542 		umb_newstate(sc, UMB_S_RADIO, UMB_NS_DONT_DROP);
1543 	return 1;
1544 }
1545 
1546 static int
umb_decode_pin(struct umb_softc * sc,void * data,int len)1547 umb_decode_pin(struct umb_softc *sc, void *data, int len)
1548 {
1549 	struct mbim_cid_pin_info *pi = data;
1550 	if_t ifp = GET_IFP(sc);
1551 	uint32_t	attempts_left;
1552 
1553 	if (len < sizeof (*pi))
1554 		return 0;
1555 
1556 	attempts_left = le32toh(pi->remaining_attempts);
1557 	if (attempts_left != 0xffffffff)
1558 		sc->sc_info.pin_attempts_left = attempts_left;
1559 
1560 	switch (le32toh(pi->state)) {
1561 	case MBIM_PIN_STATE_UNLOCKED:
1562 		sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1563 		break;
1564 	case MBIM_PIN_STATE_LOCKED:
1565 		switch (le32toh(pi->type)) {
1566 		case MBIM_PIN_TYPE_PIN1:
1567 			sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1568 			break;
1569 		case MBIM_PIN_TYPE_PUK1:
1570 			sc->sc_info.pin_state = UMB_PUK_REQUIRED;
1571 			break;
1572 		case MBIM_PIN_TYPE_PIN2:
1573 		case MBIM_PIN_TYPE_PUK2:
1574 			/* Assume that PIN1 was accepted */
1575 			sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1576 			break;
1577 		}
1578 		break;
1579 	}
1580 	if (if_getflags(ifp) & IFF_DEBUG)
1581 		log(LOG_INFO, "%s: %s state %s (%d attempts left)\n",
1582 		    DEVNAM(sc), umb_pin_type(le32toh(pi->type)),
1583 		    (le32toh(pi->state) == MBIM_PIN_STATE_UNLOCKED) ?
1584 			"unlocked" : "locked",
1585 		    le32toh(pi->remaining_attempts));
1586 
1587 	/*
1588 	 * In case the PIN was set after IFF_UP, retrigger the state machine
1589 	 */
1590 	umb_add_task(sc, umb_state_task,
1591 			&sc->sc_proc_state_task[0].hdr,
1592 			&sc->sc_proc_state_task[1].hdr, 0);
1593 	return 1;
1594 }
1595 
1596 static int
umb_decode_packet_service(struct umb_softc * sc,void * data,int len)1597 umb_decode_packet_service(struct umb_softc *sc, void *data, int len)
1598 {
1599 	struct mbim_cid_packet_service_info *psi = data;
1600 	int	 state, highestclass;
1601 	uint64_t up_speed, down_speed;
1602 	if_t ifp = GET_IFP(sc);
1603 
1604 	if (len < sizeof (*psi))
1605 		return 0;
1606 
1607 	sc->sc_info.nwerror = le32toh(psi->nwerror);
1608 	state = le32toh(psi->state);
1609 	highestclass = le32toh(psi->highest_dataclass);
1610 	up_speed = le64toh(psi->uplink_speed);
1611 	down_speed = le64toh(psi->downlink_speed);
1612 	if (sc->sc_info.packetstate  != state ||
1613 	    sc->sc_info.uplink_speed != up_speed ||
1614 	    sc->sc_info.downlink_speed != down_speed) {
1615 		if (if_getflags(ifp) & IFF_DEBUG) {
1616 			log(LOG_INFO, "%s: packet service ", DEVNAM(sc));
1617 			if (sc->sc_info.packetstate  != state)
1618 				log(LOG_INFO, "changed from %s to ",
1619 				    umb_packet_state(sc->sc_info.packetstate));
1620 			log(LOG_INFO, "%s, class %s, speed: %" PRIu64 " up / %" PRIu64 " down\n",
1621 			    umb_packet_state(state),
1622 			    umb_dataclass(highestclass), up_speed, down_speed);
1623 		}
1624 	}
1625 	sc->sc_info.packetstate = state;
1626 	sc->sc_info.highestclass = highestclass;
1627 	sc->sc_info.uplink_speed = up_speed;
1628 	sc->sc_info.downlink_speed = down_speed;
1629 
1630 	if (sc->sc_info.regmode == MBIM_REGMODE_AUTOMATIC) {
1631 		/*
1632 		 * For devices using automatic registration mode, just proceed,
1633 		 * once registration has completed.
1634 		 */
1635 		if (if_getflags(ifp) & IFF_UP) {
1636 			switch (sc->sc_info.regstate) {
1637 			case MBIM_REGSTATE_HOME:
1638 			case MBIM_REGSTATE_ROAMING:
1639 			case MBIM_REGSTATE_PARTNER:
1640 				umb_newstate(sc, UMB_S_ATTACHED,
1641 				    UMB_NS_DONT_DROP);
1642 				break;
1643 			default:
1644 				break;
1645 			}
1646 		} else
1647 			umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1648 	} else switch (sc->sc_info.packetstate) {
1649 	case MBIM_PKTSERVICE_STATE_ATTACHED:
1650 		umb_newstate(sc, UMB_S_ATTACHED, UMB_NS_DONT_DROP);
1651 		break;
1652 	case MBIM_PKTSERVICE_STATE_DETACHED:
1653 		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1654 		break;
1655 	}
1656 	return 1;
1657 }
1658 
1659 static int
umb_decode_signal_state(struct umb_softc * sc,void * data,int len)1660 umb_decode_signal_state(struct umb_softc *sc, void *data, int len)
1661 {
1662 	struct mbim_cid_signal_state *ss = data;
1663 	if_t ifp = GET_IFP(sc);
1664 	int	 rssi;
1665 
1666 	if (len < sizeof (*ss))
1667 		return 0;
1668 
1669 	if (le32toh(ss->rssi) == 99)
1670 		rssi = UMB_VALUE_UNKNOWN;
1671 	else {
1672 		rssi = -113 + 2 * le32toh(ss->rssi);
1673 		if ((if_getflags(ifp) & IFF_DEBUG) && sc->sc_info.rssi != rssi &&
1674 		    sc->sc_state >= UMB_S_CONNECTED)
1675 			log(LOG_INFO, "%s: rssi %d dBm\n", DEVNAM(sc), rssi);
1676 	}
1677 	sc->sc_info.rssi = rssi;
1678 	sc->sc_info.ber = le32toh(ss->err_rate);
1679 	if (sc->sc_info.ber == -99)
1680 		sc->sc_info.ber = UMB_VALUE_UNKNOWN;
1681 	return 1;
1682 }
1683 
1684 static int
umb_decode_connect_info(struct umb_softc * sc,void * data,int len)1685 umb_decode_connect_info(struct umb_softc *sc, void *data, int len)
1686 {
1687 	struct mbim_cid_connect_info *ci = data;
1688 	if_t ifp = GET_IFP(sc);
1689 	int	 act;
1690 
1691 	if (len < sizeof (*ci))
1692 		return 0;
1693 
1694 	if (le32toh(ci->sessionid) != umb_session_id) {
1695 		DPRINTF("discard connection info for session %u\n",
1696 		    le32toh(ci->sessionid));
1697 		return 1;
1698 	}
1699 	if (memcmp(ci->context, umb_uuid_context_internet,
1700 	    sizeof (ci->context))) {
1701 		DPRINTF("discard connection info for other context\n");
1702 		return 1;
1703 	}
1704 	act = le32toh(ci->activation);
1705 	if (sc->sc_info.activation != act) {
1706 		if (if_getflags(ifp) & IFF_DEBUG)
1707 			log(LOG_INFO, "%s: connection %s\n", DEVNAM(sc),
1708 			    umb_activation(act));
1709 		if ((if_getflags(ifp) & IFF_DEBUG) &&
1710 		    le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_DEFAULT &&
1711 		    le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_IPV4)
1712 			log(LOG_DEBUG, "%s: got iptype %d connection\n",
1713 			    DEVNAM(sc), le32toh(ci->iptype));
1714 
1715 		sc->sc_info.activation = act;
1716 		sc->sc_info.nwerror = le32toh(ci->nwerror);
1717 
1718 		if (sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED)
1719 			umb_newstate(sc, UMB_S_CONNECTED, UMB_NS_DONT_DROP);
1720 		else if (sc->sc_info.activation ==
1721 		    MBIM_ACTIVATION_STATE_DEACTIVATED)
1722 			umb_newstate(sc, UMB_S_ATTACHED, 0);
1723 		/* else: other states are purely transitional */
1724 	}
1725 	return 1;
1726 }
1727 
1728 static int
umb_add_inet_config(struct umb_softc * sc,struct in_addr ip,u_int prefixlen,struct in_addr gw)1729 umb_add_inet_config(struct umb_softc *sc, struct in_addr ip, u_int prefixlen,
1730     struct in_addr gw)
1731 {
1732 	if_t ifp = GET_IFP(sc);
1733 	struct in_aliasreq ifra;
1734 	struct sockaddr_in *sin;
1735 	int	 rv;
1736 
1737 	memset(&ifra, 0, sizeof (ifra));
1738 	sin = (struct sockaddr_in *)&ifra.ifra_addr;
1739 	sin->sin_family = AF_INET;
1740 	sin->sin_len = sizeof (*sin);
1741 	sin->sin_addr = ip;
1742 
1743 	sin = (struct sockaddr_in *)&ifra.ifra_dstaddr;
1744 	sin->sin_family = AF_INET;
1745 	sin->sin_len = sizeof (*sin);
1746 	sin->sin_addr = gw;
1747 
1748 	sin = (struct sockaddr_in *)&ifra.ifra_mask;
1749 	sin->sin_family = AF_INET;
1750 	sin->sin_len = sizeof (*sin);
1751 	umb_in_len2mask(&sin->sin_addr,
1752 	    MIN(prefixlen, sizeof (struct in_addr) * 8));
1753 
1754 	mtx_unlock(&sc->sc_mutex);
1755 	CURVNET_SET_QUIET(if_getvnet(ifp));
1756 	rv = in_control(NULL, SIOCAIFADDR, (caddr_t)&ifra, ifp, curthread);
1757 	CURVNET_RESTORE();
1758 	mtx_lock(&sc->sc_mutex);
1759 	if (rv != 0) {
1760 		device_printf(sc->sc_dev, "unable to set IPv4 address, error %d\n",
1761 		    rv);
1762 		return rv;
1763 	}
1764 
1765 	if (if_getflags(ifp) & IFF_DEBUG)
1766 		log(LOG_INFO, "%s: IPv4 addr %s, mask %s, "
1767 		    "gateway %s\n", DEVNAM(sc),
1768 		    umb_ntop(sintosa(&ifra.ifra_addr)),
1769 		    umb_ntop(sintosa(&ifra.ifra_mask)),
1770 		    umb_ntop(sintosa(&ifra.ifra_dstaddr)));
1771 
1772 	return 0;
1773 }
1774 
1775 static int
umb_decode_ip_configuration(struct umb_softc * sc,void * data,int len)1776 umb_decode_ip_configuration(struct umb_softc *sc, void *data, int len)
1777 {
1778 	struct mbim_cid_ip_configuration_info *ic = data;
1779 	if_t ifp = GET_IFP(sc);
1780 	uint32_t avail_v4;
1781 	uint32_t val;
1782 	int	 n, i;
1783 	int	 off;
1784 	struct mbim_cid_ipv4_element ipv4elem;
1785 	struct in_addr addr, gw;
1786 	int	 state = -1;
1787 	int	 rv;
1788 
1789 	if (len < sizeof (*ic))
1790 		return 0;
1791 	if (le32toh(ic->sessionid) != umb_session_id) {
1792 		DPRINTF("ignore IP configuration for session id %d\n",
1793 		    le32toh(ic->sessionid));
1794 		return 0;
1795 	}
1796 
1797 	/*
1798 	 * IPv4 configuration
1799 	 */
1800 	avail_v4 = le32toh(ic->ipv4_available);
1801 	if ((avail_v4 & (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) ==
1802 	    (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) {
1803 		n = le32toh(ic->ipv4_naddr);
1804 		off = le32toh(ic->ipv4_addroffs);
1805 
1806 		if (n == 0 || off + sizeof (ipv4elem) > len)
1807 			goto tryv6;
1808 		if (n != 1 && if_getflags(ifp) & IFF_DEBUG)
1809 			log(LOG_INFO, "%s: more than one IPv4 addr: %d\n",
1810 			    DEVNAM(sc), n);
1811 
1812 		/* Only pick the first one */
1813 		memcpy(&ipv4elem, (char *)data + off, sizeof (ipv4elem));
1814 		ipv4elem.prefixlen = le32toh(ipv4elem.prefixlen);
1815 		addr.s_addr = ipv4elem.addr;
1816 
1817 		off = le32toh(ic->ipv4_gwoffs);
1818 		if (off + sizeof (gw) > len)
1819 			goto done;
1820 		memcpy(&gw, (char *)data + off, sizeof (gw));
1821 
1822 		rv = umb_add_inet_config(sc, addr, ipv4elem.prefixlen, gw);
1823 		if (rv == 0)
1824 			state = UMB_S_UP;
1825 	}
1826 
1827 	memset(sc->sc_info.ipv4dns, 0, sizeof (sc->sc_info.ipv4dns));
1828 	if (avail_v4 & MBIM_IPCONF_HAS_DNSINFO) {
1829 		n = le32toh(ic->ipv4_ndnssrv);
1830 		off = le32toh(ic->ipv4_dnssrvoffs);
1831 		i = 0;
1832 		while (n-- > 0) {
1833 			if (off + sizeof (addr) > len)
1834 				break;
1835 			memcpy(&addr, (char *)data + off, sizeof(addr));
1836 			if (i < UMB_MAX_DNSSRV)
1837 				sc->sc_info.ipv4dns[i++] = addr;
1838 			off += sizeof(addr);
1839 		}
1840 	}
1841 
1842 	if ((avail_v4 & MBIM_IPCONF_HAS_MTUINFO)) {
1843 		val = le32toh(ic->ipv4_mtu);
1844 		if (if_getmtu(ifp) != val && val <= sc->sc_maxpktlen) {
1845 			if_setmtu(ifp, val);
1846 			if (if_getmtu(ifp) > val)
1847 				if_setmtu(ifp, val);
1848 			if (if_getflags(ifp) & IFF_DEBUG)
1849 				log(LOG_INFO, "%s: MTU %d\n", DEVNAM(sc), val);
1850 		}
1851 	}
1852 
1853 	avail_v4 = le32toh(ic->ipv6_available);
1854 	if ((if_getflags(ifp) & IFF_DEBUG) && avail_v4 & MBIM_IPCONF_HAS_ADDRINFO) {
1855 		/* XXX FIXME: IPv6 configuration missing */
1856 		log(LOG_INFO, "%s: ignoring IPv6 configuration\n", DEVNAM(sc));
1857 	}
1858 	if (state != -1)
1859 		umb_newstate(sc, state, 0);
1860 
1861 tryv6:
1862 done:
1863 	return 1;
1864 }
1865 
1866 static void
umb_rx(struct umb_softc * sc)1867 umb_rx(struct umb_softc *sc)
1868 {
1869 	mtx_assert(&sc->sc_mutex, MA_OWNED);
1870 
1871 	usbd_transfer_start(sc->sc_xfer[UMB_BULK_RX]);
1872 }
1873 
1874 static void
umb_rxeof(struct usb_xfer * xfer,usb_error_t status)1875 umb_rxeof(struct usb_xfer *xfer, usb_error_t status)
1876 {
1877 	struct umb_softc *sc = usbd_xfer_softc(xfer);
1878 	if_t ifp = GET_IFP(sc);
1879 	int actlen;
1880 	int aframes;
1881 	int i;
1882 
1883 	DPRINTF("%s(%u): state=%u\n", __func__, status, USB_GET_STATE(xfer));
1884 
1885 	mtx_assert(&sc->sc_mutex, MA_OWNED);
1886 
1887 	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
1888 
1889 	switch (USB_GET_STATE(xfer)) {
1890 	case USB_ST_TRANSFERRED:
1891 		DPRINTF("received %u bytes in %u frames\n", actlen, aframes);
1892 
1893 		if (actlen == 0) {
1894 			if (sc->sc_rx_nerr >= 4)
1895 				/* throttle transfers */
1896 				usbd_xfer_set_interval(xfer, 500);
1897 			else
1898 				sc->sc_rx_nerr++;
1899 		}
1900 		else {
1901 			/* disable throttling */
1902 			usbd_xfer_set_interval(xfer, 0);
1903 			sc->sc_rx_nerr = 0;
1904 		}
1905 
1906 		for(i = 0; i < aframes; i++) {
1907 			umb_decap(sc, xfer, i);
1908 		}
1909 
1910 		/* fall through */
1911 	case USB_ST_SETUP:
1912 		usbd_xfer_set_frame_data(xfer, 0, sc->sc_rx_buf,
1913 				sc->sc_rx_bufsz);
1914 		usbd_xfer_set_frames(xfer, 1);
1915 		usbd_transfer_submit(xfer);
1916 
1917 		umb_rxflush(sc);
1918 		break;
1919 	default:
1920 		DPRINTF("rx error: %s\n", usbd_errstr(status));
1921 
1922 		/* disable throttling */
1923 		usbd_xfer_set_interval(xfer, 0);
1924 
1925 		if (status != USB_ERR_CANCELLED) {
1926 			/* try to clear stall first */
1927 			usbd_xfer_set_stall(xfer);
1928 			usbd_xfer_set_frames(xfer, 0);
1929 			usbd_transfer_submit(xfer);
1930 			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1931 		}
1932 		else if (++sc->sc_rx_nerr > 100) {
1933 			log(LOG_ERR, "%s: too many rx errors, disabling\n",
1934 			    DEVNAM(sc));
1935 			umb_deactivate(sc->sc_dev);
1936 		}
1937 		break;
1938 	}
1939 }
1940 
1941 static void
umb_rxflush(struct umb_softc * sc)1942 umb_rxflush(struct umb_softc *sc)
1943 {
1944 	if_t ifp = GET_IFP(sc);
1945 	struct mbuf *m;
1946 
1947 	mtx_assert(&sc->sc_mutex, MA_OWNED);
1948 
1949 	for (;;) {
1950 		_IF_DEQUEUE(&sc->sc_rx_queue, m);
1951 		if (m == NULL)
1952 			break;
1953 
1954 		/*
1955 		 * The USB xfer has been resubmitted so it's safe to unlock now.
1956 		 */
1957 		mtx_unlock(&sc->sc_mutex);
1958 		CURVNET_SET_QUIET(if_getvnet(ifp));
1959 		if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
1960 			if_input(ifp, m);
1961 		else
1962 			m_freem(m);
1963 		CURVNET_RESTORE();
1964 		mtx_lock(&sc->sc_mutex);
1965 	}
1966 }
1967 
1968 static int
umb_encap(struct umb_softc * sc,struct mbuf * m,struct usb_xfer * xfer)1969 umb_encap(struct umb_softc *sc, struct mbuf *m, struct usb_xfer *xfer)
1970 {
1971 	struct ncm_header16 *hdr;
1972 	struct ncm_pointer16 *ptr;
1973 	int	 len;
1974 
1975 	KASSERT(sc->sc_tx_m == NULL,
1976 			("Assertion failed in umb_encap()"));
1977 
1978 	/* All size constraints have been validated by the caller! */
1979 	hdr = (struct ncm_header16 *)sc->sc_tx_buf;
1980 	ptr = (struct ncm_pointer16 *)(hdr + 1);
1981 
1982 	USETDW(hdr->dwSignature, NCM_HDR16_SIG);
1983 	USETW(hdr->wHeaderLength, sizeof (*hdr));
1984 	USETW(hdr->wSequence, sc->sc_tx_seq);
1985 	sc->sc_tx_seq++;
1986 	USETW(hdr->wNdpIndex, sizeof (*hdr));
1987 
1988 	len = m->m_pkthdr.len;
1989 	USETDW(ptr->dwSignature, MBIM_NCM_NTH16_SIG(umb_session_id));
1990 	USETW(ptr->wLength, sizeof (*ptr));
1991 	USETW(ptr->wNextNdpIndex, 0);
1992 	USETW(ptr->dgram[0].wDatagramIndex, MBIM_HDR16_LEN);
1993 	USETW(ptr->dgram[0].wDatagramLen, len);
1994 	USETW(ptr->dgram[1].wDatagramIndex, 0);
1995 	USETW(ptr->dgram[1].wDatagramLen, 0);
1996 
1997 	KASSERT(len + MBIM_HDR16_LEN <= sc->sc_tx_bufsz,
1998 			("Assertion failed in umb_encap()"));
1999 	m_copydata(m, 0, len, (char *)(ptr + 1));
2000 	sc->sc_tx_m = m;
2001 	len += MBIM_HDR16_LEN;
2002 	USETW(hdr->wBlockLength, len);
2003 
2004 	usbd_xfer_set_frame_data(xfer, 0, sc->sc_tx_buf, len);
2005 	usbd_xfer_set_interval(xfer, 0);
2006 	usbd_xfer_set_frames(xfer, 1);
2007 
2008 	DPRINTFN(3, "%s: encap %d bytes\n", DEVNAM(sc), len);
2009 	DDUMPN(5, sc->sc_tx_buf, len);
2010 	return 0;
2011 }
2012 
2013 static void
umb_txeof(struct usb_xfer * xfer,usb_error_t status)2014 umb_txeof(struct usb_xfer *xfer, usb_error_t status)
2015 {
2016 	struct umb_softc *sc = usbd_xfer_softc(xfer);
2017 	if_t ifp = GET_IFP(sc);
2018 	struct mbuf *m;
2019 
2020 	DPRINTF("%s(%u) state=%u\n", __func__, status, USB_GET_STATE(xfer));
2021 
2022 	mtx_assert(&sc->sc_mutex, MA_OWNED);
2023 
2024 	switch (USB_GET_STATE(xfer)) {
2025 	case USB_ST_TRANSFERRED:
2026 		if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
2027 		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2028 
2029 		umb_txflush(sc);
2030 
2031 		/* fall through */
2032 	case USB_ST_SETUP:
2033 tr_setup:
2034 		if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
2035 			break;
2036 
2037 		m = if_dequeue(ifp); /* XXX - IFAPI */
2038 		if (m == NULL)
2039 			break;
2040 
2041 		if (umb_encap(sc, m, xfer)) {
2042 			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2043 			umb_txflush(sc);
2044 			break;
2045 		}
2046 
2047 		BPF_MTAP(ifp, m);
2048 
2049 		if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
2050 		usbd_transfer_submit(xfer);
2051 
2052 		break;
2053 
2054 	default:
2055 		umb_txflush(sc);
2056 
2057 		/* count output errors */
2058 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2059 		DPRINTF("tx error: %s\n",
2060 				usbd_errstr(status));
2061 
2062 		if (status != USB_ERR_CANCELLED) {
2063 			/* try to clear stall first */
2064 			usbd_xfer_set_stall(xfer);
2065 			goto tr_setup;
2066 		}
2067 		break;
2068 	}
2069 }
2070 
2071 static void
umb_txflush(struct umb_softc * sc)2072 umb_txflush(struct umb_softc *sc)
2073 {
2074 	mtx_assert(&sc->sc_mutex, MA_OWNED);
2075 
2076 	if (sc->sc_tx_m != NULL) {
2077 		m_freem(sc->sc_tx_m);
2078 		sc->sc_tx_m = NULL;
2079 	}
2080 }
2081 
2082 static void
umb_decap(struct umb_softc * sc,struct usb_xfer * xfer,int frame)2083 umb_decap(struct umb_softc *sc, struct usb_xfer *xfer, int frame)
2084 {
2085 	if_t ifp = GET_IFP(sc);
2086 	char *buf;
2087 	int len;
2088 	char	*dp;
2089 	struct ncm_header16 *hdr16;
2090 	struct ncm_header32 *hdr32;
2091 	struct ncm_pointer16 *ptr16;
2092 	struct ncm_pointer16_dgram *dgram16;
2093 	struct ncm_pointer32_dgram *dgram32;
2094 	uint32_t hsig, psig;
2095 	int	 hlen, blen;
2096 	int	 ptrlen, ptroff, dgentryoff;
2097 	uint32_t doff, dlen;
2098 	struct mbuf *m;
2099 
2100 	usbd_xfer_frame_data(xfer, frame, (void **)&buf, &len);
2101 	DPRINTFN(4, "recv %d bytes\n", len);
2102 	DDUMPN(5, buf, len);
2103 	if (len < sizeof (*hdr16))
2104 		goto toosmall;
2105 
2106 	hdr16 = (struct ncm_header16 *)buf;
2107 	hsig = UGETDW(hdr16->dwSignature);
2108 	hlen = UGETW(hdr16->wHeaderLength);
2109 	if (len < hlen)
2110 		goto toosmall;
2111 	if (len > sc->sc_rx_bufsz) {
2112 		DPRINTF("packet too large (%d)\n", len);
2113 		goto fail;
2114 	}
2115 	switch (hsig) {
2116 	case NCM_HDR16_SIG:
2117 		blen = UGETW(hdr16->wBlockLength);
2118 		ptroff = UGETW(hdr16->wNdpIndex);
2119 		if (hlen != sizeof (*hdr16)) {
2120 			DPRINTF("%s: bad header len %d for NTH16 (exp %zu)\n",
2121 			    DEVNAM(sc), hlen, sizeof (*hdr16));
2122 			goto fail;
2123 		}
2124 		break;
2125 	case NCM_HDR32_SIG:
2126 		hdr32 = (struct ncm_header32 *)hdr16;
2127 		blen = UGETDW(hdr32->dwBlockLength);
2128 		ptroff = UGETDW(hdr32->dwNdpIndex);
2129 		if (hlen != sizeof (*hdr32)) {
2130 			DPRINTF("%s: bad header len %d for NTH32 (exp %zu)\n",
2131 			    DEVNAM(sc), hlen, sizeof (*hdr32));
2132 			goto fail;
2133 		}
2134 		break;
2135 	default:
2136 		DPRINTF("%s: unsupported NCM header signature (0x%08x)\n",
2137 		    DEVNAM(sc), hsig);
2138 		goto fail;
2139 	}
2140 	if (len < blen) {
2141 		DPRINTF("%s: bad NTB len (%d) for %d bytes of data\n",
2142 		    DEVNAM(sc), blen, len);
2143 		goto fail;
2144 	}
2145 
2146 	if (len < ptroff)
2147 		goto toosmall;
2148 	ptr16 = (struct ncm_pointer16 *)(buf + ptroff);
2149 	psig = UGETDW(ptr16->dwSignature);
2150 	ptrlen = UGETW(ptr16->wLength);
2151 	if ((uint64_t)len < (uint64_t)ptrlen + (uint64_t)ptroff)
2152 		goto toosmall;
2153 	if (!MBIM_NCM_NTH16_ISISG(psig) && !MBIM_NCM_NTH32_ISISG(psig)) {
2154 		DPRINTF("%s: unsupported NCM pointer signature (0x%08x)\n",
2155 		    DEVNAM(sc), psig);
2156 		goto fail;
2157 	}
2158 
2159 	switch (hsig) {
2160 	case NCM_HDR16_SIG:
2161 		dgentryoff = offsetof(struct ncm_pointer16, dgram);
2162 		break;
2163 	case NCM_HDR32_SIG:
2164 		dgentryoff = offsetof(struct ncm_pointer32, dgram);
2165 		break;
2166 	default:
2167 		goto fail;
2168 	}
2169 
2170 	while (dgentryoff < ptrlen) {
2171 		switch (hsig) {
2172 		case NCM_HDR16_SIG:
2173 			if (ptroff + dgentryoff < sizeof (*dgram16))
2174 				goto done;
2175 			dgram16 = (struct ncm_pointer16_dgram *)
2176 			    (buf + ptroff + dgentryoff);
2177 			dgentryoff += sizeof (*dgram16);
2178 			dlen = UGETW(dgram16->wDatagramLen);
2179 			doff = UGETW(dgram16->wDatagramIndex);
2180 			break;
2181 		case NCM_HDR32_SIG:
2182 			if (ptroff + dgentryoff < sizeof (*dgram32))
2183 				goto done;
2184 			dgram32 = (struct ncm_pointer32_dgram *)
2185 			    (buf + ptroff + dgentryoff);
2186 			dgentryoff += sizeof (*dgram32);
2187 			dlen = UGETDW(dgram32->dwDatagramLen);
2188 			doff = UGETDW(dgram32->dwDatagramIndex);
2189 			break;
2190 		default:
2191 			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2192 			goto done;
2193 		}
2194 
2195 		/* Terminating zero entry */
2196 		if (dlen == 0 || doff == 0)
2197 			break;
2198 		if ((uint64_t)len < (uint64_t)dlen + (uint64_t)doff) {
2199 			/* Skip giant datagram but continue processing */
2200 			DPRINTF("%s: datagram too large (%d @ off %d)\n",
2201 			    DEVNAM(sc), dlen, doff);
2202 			continue;
2203 		}
2204 
2205 		dp = buf + doff;
2206 		DPRINTFN(3, "%s: decap %d bytes\n", DEVNAM(sc), dlen);
2207 		m = m_devget(dp, dlen, 0, ifp, NULL);
2208 		if (m == NULL) {
2209 			if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2210 			continue;
2211 		}
2212 
2213 		/* enqueue for later when the lock can be released */
2214 		_IF_ENQUEUE(&sc->sc_rx_queue, m);
2215 
2216 		if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
2217 
2218 	}
2219 done:
2220 	sc->sc_rx_nerr = 0;
2221 	return;
2222 toosmall:
2223 	DPRINTF("%s: packet too small (%d)\n", DEVNAM(sc), len);
2224 fail:
2225 	if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2226 }
2227 
2228 static usb_error_t
umb_send_encap_command(struct umb_softc * sc,void * data,int len)2229 umb_send_encap_command(struct umb_softc *sc, void *data, int len)
2230 {
2231 	usb_device_request_t req;
2232 
2233 	if (len > sc->sc_ctrl_len)
2234 		return USB_ERR_INVAL;
2235 
2236 	/* XXX FIXME: if (total len > sc->sc_ctrl_len) => must fragment */
2237 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
2238 	req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
2239 	USETW(req.wValue, 0);
2240 	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2241 	USETW(req.wLength, len);
2242 	mtx_unlock(&sc->sc_mutex);
2243 	DELAY(umb_delay);
2244 	mtx_lock(&sc->sc_mutex);
2245 	return usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, data, 0,
2246 			NULL, umb_xfer_tout);
2247 }
2248 
2249 static int
umb_get_encap_response(struct umb_softc * sc,void * buf,int * len)2250 umb_get_encap_response(struct umb_softc *sc, void *buf, int *len)
2251 {
2252 	usb_device_request_t req;
2253 	usb_error_t err;
2254 	uint16_t l = *len;
2255 
2256 	req.bmRequestType = UT_READ_CLASS_INTERFACE;
2257 	req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
2258 	USETW(req.wValue, 0);
2259 	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2260 	USETW(req.wLength, l);
2261 	/* XXX FIXME: re-assemble fragments */
2262 
2263 	mtx_unlock(&sc->sc_mutex);
2264 	DELAY(umb_delay);
2265 	mtx_lock(&sc->sc_mutex);
2266 	err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, buf,
2267 			USB_SHORT_XFER_OK, &l, umb_xfer_tout);
2268 	if (err == USB_ERR_NORMAL_COMPLETION) {
2269 		*len = l;
2270 		return 1;
2271 	}
2272 	DPRINTF("ctrl recv: %s\n", usbd_errstr(err));
2273 	return 0;
2274 }
2275 
2276 static void
umb_ctrl_msg(struct umb_softc * sc,uint32_t req,void * data,int len)2277 umb_ctrl_msg(struct umb_softc *sc, uint32_t req, void *data, int len)
2278 {
2279 	if_t ifp = GET_IFP(sc);
2280 	uint32_t tid;
2281 	struct mbim_msghdr *hdr = data;
2282 	usb_error_t err;
2283 
2284 	if (sc->sc_dying)
2285 		return;
2286 	if (len < sizeof (*hdr))
2287 		return;
2288 	tid = ++sc->sc_tid;
2289 
2290 	hdr->type = htole32(req);
2291 	hdr->len = htole32(len);
2292 	hdr->tid = htole32(tid);
2293 
2294 #ifdef UMB_DEBUG
2295 	if (umb_debug) {
2296 		const char *op, *str;
2297 		if (req == MBIM_COMMAND_MSG) {
2298 			struct mbim_h2f_cmd *c = data;
2299 			if (le32toh(c->op) == MBIM_CMDOP_SET)
2300 				op = "set";
2301 			else
2302 				op = "qry";
2303 			str = umb_cid2str(le32toh(c->cid));
2304 		} else {
2305 			op = "snd";
2306 			str = umb_request2str(req);
2307 		}
2308 		DPRINTF("-> %s %s (tid %u)\n", op, str, tid);
2309 	}
2310 #endif
2311 	err = umb_send_encap_command(sc, data, len);
2312 	if (err != USB_ERR_NORMAL_COMPLETION) {
2313 		if (if_getflags(ifp) & IFF_DEBUG)
2314 			log(LOG_ERR, "%s: send %s msg (tid %u) failed: %s\n",
2315 			    DEVNAM(sc), umb_request2str(req), tid,
2316 			    usbd_errstr(err));
2317 
2318 		/* will affect other transactions, too */
2319 		usbd_transfer_stop(sc->sc_xfer[UMB_INTR_RX]);
2320 	} else {
2321 		DPRINTFN(2, "sent %s (tid %u)\n",
2322 		    umb_request2str(req), tid);
2323 		DDUMPN(3, data, len);
2324 	}
2325 	return;
2326 }
2327 
2328 static void
umb_open(struct umb_softc * sc)2329 umb_open(struct umb_softc *sc)
2330 {
2331 	struct mbim_h2f_openmsg msg;
2332 
2333 	memset(&msg, 0, sizeof (msg));
2334 	msg.maxlen = htole32(sc->sc_ctrl_len);
2335 	umb_ctrl_msg(sc, MBIM_OPEN_MSG, &msg, sizeof (msg));
2336 	return;
2337 }
2338 
2339 static void
umb_close(struct umb_softc * sc)2340 umb_close(struct umb_softc *sc)
2341 {
2342 	struct mbim_h2f_closemsg msg;
2343 
2344 	memset(&msg, 0, sizeof (msg));
2345 	umb_ctrl_msg(sc, MBIM_CLOSE_MSG, &msg, sizeof (msg));
2346 }
2347 
2348 static int
umb_setpin(struct umb_softc * sc,int op,int is_puk,void * pin,int pinlen,void * newpin,int newpinlen)2349 umb_setpin(struct umb_softc *sc, int op, int is_puk, void *pin, int pinlen,
2350     void *newpin, int newpinlen)
2351 {
2352 	struct mbim_cid_pin cp;
2353 	int	 off;
2354 
2355 	if (pinlen == 0)
2356 		return 0;
2357 	if (pinlen < 0 || pinlen > MBIM_PIN_MAXLEN ||
2358 	    newpinlen < 0 || newpinlen > MBIM_PIN_MAXLEN ||
2359 	    op < 0 || op > MBIM_PIN_OP_CHANGE ||
2360 	    (is_puk && op != MBIM_PIN_OP_ENTER))
2361 		return EINVAL;
2362 
2363 	memset(&cp, 0, sizeof (cp));
2364 	cp.type = htole32(is_puk ? MBIM_PIN_TYPE_PUK1 : MBIM_PIN_TYPE_PIN1);
2365 
2366 	off = offsetof(struct mbim_cid_pin, data);
2367 	if (!umb_addstr(&cp, sizeof (cp), &off, pin, pinlen,
2368 	    &cp.pin_offs, &cp.pin_size))
2369 		return EINVAL;
2370 
2371 	cp.op  = htole32(op);
2372 	if (newpinlen) {
2373 		if (!umb_addstr(&cp, sizeof (cp), &off, newpin, newpinlen,
2374 		    &cp.newpin_offs, &cp.newpin_size))
2375 			return EINVAL;
2376 	} else {
2377 		if ((op == MBIM_PIN_OP_CHANGE) || is_puk)
2378 			return EINVAL;
2379 		if (!umb_addstr(&cp, sizeof (cp), &off, NULL, 0,
2380 		    &cp.newpin_offs, &cp.newpin_size))
2381 			return EINVAL;
2382 	}
2383 	mtx_lock(&sc->sc_mutex);
2384 	umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_SET, &cp, off);
2385 	mtx_unlock(&sc->sc_mutex);
2386 	return 0;
2387 }
2388 
2389 static void
umb_setdataclass(struct umb_softc * sc)2390 umb_setdataclass(struct umb_softc *sc)
2391 {
2392 	struct mbim_cid_registration_state rs;
2393 	uint32_t	 classes;
2394 
2395 	if (sc->sc_info.supportedclasses == MBIM_DATACLASS_NONE)
2396 		return;
2397 
2398 	memset(&rs, 0, sizeof (rs));
2399 	rs.regaction = htole32(MBIM_REGACTION_AUTOMATIC);
2400 	classes = sc->sc_info.supportedclasses;
2401 	if (sc->sc_info.preferredclasses != MBIM_DATACLASS_NONE)
2402 		classes &= sc->sc_info.preferredclasses;
2403 	rs.data_class = htole32(classes);
2404 	mtx_lock(&sc->sc_mutex);
2405 	umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_SET, &rs, sizeof (rs));
2406 	mtx_unlock(&sc->sc_mutex);
2407 }
2408 
2409 static void
umb_radio(struct umb_softc * sc,int on)2410 umb_radio(struct umb_softc *sc, int on)
2411 {
2412 	struct mbim_cid_radio_state s;
2413 
2414 	DPRINTF("set radio %s\n", on ? "on" : "off");
2415 	memset(&s, 0, sizeof (s));
2416 	s.state = htole32(on ? MBIM_RADIO_STATE_ON : MBIM_RADIO_STATE_OFF);
2417 	umb_cmd(sc, MBIM_CID_RADIO_STATE, MBIM_CMDOP_SET, &s, sizeof (s));
2418 }
2419 
2420 static void
umb_allocate_cid(struct umb_softc * sc)2421 umb_allocate_cid(struct umb_softc *sc)
2422 {
2423 	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2424 	    umb_qmi_alloc_cid, sizeof (umb_qmi_alloc_cid), umb_uuid_qmi_mbim);
2425 }
2426 
2427 static void
umb_send_fcc_auth(struct umb_softc * sc)2428 umb_send_fcc_auth(struct umb_softc *sc)
2429 {
2430 	uint8_t	 fccauth[sizeof (umb_qmi_fcc_auth)];
2431 
2432 	if (sc->sc_cid == -1) {
2433 		DPRINTF("missing CID, cannot send FCC auth\n");
2434 		umb_allocate_cid(sc);
2435 		return;
2436 	}
2437 	memcpy(fccauth, umb_qmi_fcc_auth, sizeof (fccauth));
2438 	fccauth[UMB_QMI_CID_OFFS] = sc->sc_cid;
2439 	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2440 	    fccauth, sizeof (fccauth), umb_uuid_qmi_mbim);
2441 }
2442 
2443 static void
umb_packet_service(struct umb_softc * sc,int attach)2444 umb_packet_service(struct umb_softc *sc, int attach)
2445 {
2446 	struct mbim_cid_packet_service	s;
2447 
2448 	DPRINTF("%s packet service\n",
2449 	    attach ? "attach" : "detach");
2450 	memset(&s, 0, sizeof (s));
2451 	s.action = htole32(attach ?
2452 	    MBIM_PKTSERVICE_ACTION_ATTACH : MBIM_PKTSERVICE_ACTION_DETACH);
2453 	umb_cmd(sc, MBIM_CID_PACKET_SERVICE, MBIM_CMDOP_SET, &s, sizeof (s));
2454 }
2455 
2456 static void
umb_connect(struct umb_softc * sc)2457 umb_connect(struct umb_softc *sc)
2458 {
2459 	if_t ifp = GET_IFP(sc);
2460 
2461 	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
2462 		log(LOG_INFO, "%s: connection disabled in roaming network\n",
2463 		    DEVNAM(sc));
2464 		return;
2465 	}
2466 	if (if_getflags(ifp) & IFF_DEBUG)
2467 		log(LOG_DEBUG, "%s: connecting ...\n", DEVNAM(sc));
2468 	umb_send_connect(sc, MBIM_CONNECT_ACTIVATE);
2469 }
2470 
2471 static void
umb_disconnect(struct umb_softc * sc)2472 umb_disconnect(struct umb_softc *sc)
2473 {
2474 	if_t ifp = GET_IFP(sc);
2475 
2476 	if (if_getflags(ifp) & IFF_DEBUG)
2477 		log(LOG_DEBUG, "%s: disconnecting ...\n", DEVNAM(sc));
2478 	umb_send_connect(sc, MBIM_CONNECT_DEACTIVATE);
2479 }
2480 
2481 static void
umb_send_connect(struct umb_softc * sc,int command)2482 umb_send_connect(struct umb_softc *sc, int command)
2483 {
2484 	struct mbim_cid_connect *c;
2485 	int	 off;
2486 
2487 	/* Too large for the stack */
2488 	mtx_unlock(&sc->sc_mutex);
2489 	c = malloc(sizeof (*c), M_MBIM_CID_CONNECT, M_WAITOK | M_ZERO);
2490 	mtx_lock(&sc->sc_mutex);
2491 	c->sessionid = htole32(umb_session_id);
2492 	c->command = htole32(command);
2493 	off = offsetof(struct mbim_cid_connect, data);
2494 	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.apn,
2495 	    sc->sc_info.apnlen, &c->access_offs, &c->access_size))
2496 		goto done;
2497 	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.username,
2498 	    sc->sc_info.usernamelen, &c->user_offs, &c->user_size))
2499 		goto done;
2500 	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.password,
2501 	    sc->sc_info.passwordlen, &c->passwd_offs, &c->passwd_size))
2502 		goto done;
2503 	c->authprot = htole32(MBIM_AUTHPROT_NONE);
2504 	c->compression = htole32(MBIM_COMPRESSION_NONE);
2505 	c->iptype = htole32(MBIM_CONTEXT_IPTYPE_IPV4);
2506 	memcpy(c->context, umb_uuid_context_internet, sizeof (c->context));
2507 	umb_cmd(sc, MBIM_CID_CONNECT, MBIM_CMDOP_SET, c, off);
2508 done:
2509 	free(c, M_MBIM_CID_CONNECT);
2510 	return;
2511 }
2512 
2513 static void
umb_qry_ipconfig(struct umb_softc * sc)2514 umb_qry_ipconfig(struct umb_softc *sc)
2515 {
2516 	struct mbim_cid_ip_configuration_info ipc;
2517 
2518 	memset(&ipc, 0, sizeof (ipc));
2519 	ipc.sessionid = htole32(umb_session_id);
2520 	umb_cmd(sc, MBIM_CID_IP_CONFIGURATION, MBIM_CMDOP_QRY,
2521 	    &ipc, sizeof (ipc));
2522 }
2523 
2524 static void
umb_cmd(struct umb_softc * sc,int cid,int op,const void * data,int len)2525 umb_cmd(struct umb_softc *sc, int cid, int op, const void *data, int len)
2526 {
2527 	umb_cmd1(sc, cid, op, data, len, umb_uuid_basic_connect);
2528 }
2529 
2530 static void
umb_cmd1(struct umb_softc * sc,int cid,int op,const void * data,int len,uint8_t * uuid)2531 umb_cmd1(struct umb_softc *sc, int cid, int op, const void *data, int len,
2532     uint8_t *uuid)
2533 {
2534 	struct mbim_h2f_cmd *cmd;
2535 	int	totlen;
2536 
2537 	/* XXX FIXME support sending fragments */
2538 	if (sizeof (*cmd) + len > sc->sc_ctrl_len) {
2539 		DPRINTF("set %s msg too long: cannot send\n",
2540 		    umb_cid2str(cid));
2541 		return;
2542 	}
2543 	cmd = sc->sc_ctrl_msg;
2544 	memset(cmd, 0, sizeof (*cmd));
2545 	cmd->frag.nfrag = htole32(1);
2546 	memcpy(cmd->devid, uuid, sizeof (cmd->devid));
2547 	cmd->cid = htole32(cid);
2548 	cmd->op = htole32(op);
2549 	cmd->infolen = htole32(len);
2550 	totlen = sizeof (*cmd);
2551 	if (len > 0) {
2552 		memcpy(cmd + 1, data, len);
2553 		totlen += len;
2554 	}
2555 	umb_ctrl_msg(sc, MBIM_COMMAND_MSG, cmd, totlen);
2556 }
2557 
2558 static void
umb_command_done(struct umb_softc * sc,void * data,int len)2559 umb_command_done(struct umb_softc *sc, void *data, int len)
2560 {
2561 	struct mbim_f2h_cmddone *cmd = data;
2562 	if_t ifp = GET_IFP(sc);
2563 	uint32_t status;
2564 	uint32_t cid;
2565 	uint32_t infolen;
2566 	int	 qmimsg = 0;
2567 
2568 	if (len < sizeof (*cmd)) {
2569 		DPRINTF("discard short %s message\n",
2570 		    umb_request2str(le32toh(cmd->hdr.type)));
2571 		return;
2572 	}
2573 	cid = le32toh(cmd->cid);
2574 	if (memcmp(cmd->devid, umb_uuid_basic_connect, sizeof (cmd->devid))) {
2575 		if (memcmp(cmd->devid, umb_uuid_qmi_mbim,
2576 		    sizeof (cmd->devid))) {
2577 			DPRINTF("discard %s message for other UUID '%s'\n",
2578 			    umb_request2str(le32toh(cmd->hdr.type)),
2579 			    umb_uuid2str(cmd->devid));
2580 			return;
2581 		} else
2582 			qmimsg = 1;
2583 	}
2584 
2585 	status = le32toh(cmd->status);
2586 	switch (status) {
2587 	case MBIM_STATUS_SUCCESS:
2588 		break;
2589 	case MBIM_STATUS_NOT_INITIALIZED:
2590 		if (if_getflags(ifp) & IFF_DEBUG)
2591 			log(LOG_ERR, "%s: SIM not initialized (PIN missing)\n",
2592 			    DEVNAM(sc));
2593 		return;
2594 	case MBIM_STATUS_PIN_REQUIRED:
2595 		sc->sc_info.pin_state = UMB_PIN_REQUIRED;
2596 		/*FALLTHROUGH*/
2597 	default:
2598 		if (if_getflags(ifp) & IFF_DEBUG)
2599 			log(LOG_ERR, "%s: set/qry %s failed: %s\n", DEVNAM(sc),
2600 			    umb_cid2str(cid), umb_status2str(status));
2601 		return;
2602 	}
2603 
2604 	infolen = le32toh(cmd->infolen);
2605 	if (len < sizeof (*cmd) + infolen) {
2606 		DPRINTF("discard truncated %s message (want %d, got %d)\n",
2607 		    umb_cid2str(cid),
2608 		    (int)sizeof (*cmd) + infolen, len);
2609 		return;
2610 	}
2611 	if (qmimsg) {
2612 		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED)
2613 			umb_decode_qmi(sc, cmd->info, infolen);
2614 	} else {
2615 		DPRINTFN(2, "set/qry %s done\n",
2616 		    umb_cid2str(cid));
2617 		umb_decode_cid(sc, cid, cmd->info, infolen);
2618 	}
2619 }
2620 
2621 static void
umb_decode_cid(struct umb_softc * sc,uint32_t cid,void * data,int len)2622 umb_decode_cid(struct umb_softc *sc, uint32_t cid, void *data, int len)
2623 {
2624 	int	 ok = 1;
2625 
2626 	switch (cid) {
2627 	case MBIM_CID_DEVICE_CAPS:
2628 		ok = umb_decode_devices_caps(sc, data, len);
2629 		break;
2630 	case MBIM_CID_SUBSCRIBER_READY_STATUS:
2631 		ok = umb_decode_subscriber_status(sc, data, len);
2632 		break;
2633 	case MBIM_CID_RADIO_STATE:
2634 		ok = umb_decode_radio_state(sc, data, len);
2635 		break;
2636 	case MBIM_CID_PIN:
2637 		ok = umb_decode_pin(sc, data, len);
2638 		break;
2639 	case MBIM_CID_REGISTER_STATE:
2640 		ok = umb_decode_register_state(sc, data, len);
2641 		break;
2642 	case MBIM_CID_PACKET_SERVICE:
2643 		ok = umb_decode_packet_service(sc, data, len);
2644 		break;
2645 	case MBIM_CID_SIGNAL_STATE:
2646 		ok = umb_decode_signal_state(sc, data, len);
2647 		break;
2648 	case MBIM_CID_CONNECT:
2649 		ok = umb_decode_connect_info(sc, data, len);
2650 		break;
2651 	case MBIM_CID_IP_CONFIGURATION:
2652 		ok = umb_decode_ip_configuration(sc, data, len);
2653 		break;
2654 	default:
2655 		/*
2656 		 * Note: the above list is incomplete and only contains
2657 		 *	mandatory CIDs from the BASIC_CONNECT set.
2658 		 *	So alternate values are not unusual.
2659 		 */
2660 		DPRINTFN(4, "ignore %s\n", umb_cid2str(cid));
2661 		break;
2662 	}
2663 	if (!ok)
2664 		DPRINTF("discard %s with bad info length %d\n",
2665 		    umb_cid2str(cid), len);
2666 	return;
2667 }
2668 
2669 static void
umb_decode_qmi(struct umb_softc * sc,uint8_t * data,int len)2670 umb_decode_qmi(struct umb_softc *sc, uint8_t *data, int len)
2671 {
2672 	uint8_t	srv;
2673 	uint16_t msg, tlvlen;
2674 	uint32_t val;
2675 
2676 #define UMB_QMI_QMUXLEN		6
2677 	if (len < UMB_QMI_QMUXLEN)
2678 		goto tooshort;
2679 
2680 	srv = data[4];
2681 	data += UMB_QMI_QMUXLEN;
2682 	len -= UMB_QMI_QMUXLEN;
2683 
2684 #define UMB_GET16(p)	((uint16_t)*p | (uint16_t)*(p + 1) << 8)
2685 #define UMB_GET32(p)	((uint32_t)*p | (uint32_t)*(p + 1) << 8 | \
2686 			    (uint32_t)*(p + 2) << 16 |(uint32_t)*(p + 3) << 24)
2687 	switch (srv) {
2688 	case 0:	/* ctl */
2689 #define UMB_QMI_CTLLEN		6
2690 		if (len < UMB_QMI_CTLLEN)
2691 			goto tooshort;
2692 		msg = UMB_GET16(&data[2]);
2693 		tlvlen = UMB_GET16(&data[4]);
2694 		data += UMB_QMI_CTLLEN;
2695 		len -= UMB_QMI_CTLLEN;
2696 		break;
2697 	case 2:	/* dms  */
2698 #define UMB_QMI_DMSLEN		7
2699 		if (len < UMB_QMI_DMSLEN)
2700 			goto tooshort;
2701 		msg = UMB_GET16(&data[3]);
2702 		tlvlen = UMB_GET16(&data[5]);
2703 		data += UMB_QMI_DMSLEN;
2704 		len -= UMB_QMI_DMSLEN;
2705 		break;
2706 	default:
2707 		DPRINTF("discard QMI message for unknown service type %d\n",
2708 		    srv);
2709 		return;
2710 	}
2711 
2712 	if (len < tlvlen)
2713 		goto tooshort;
2714 
2715 #define UMB_QMI_TLVLEN		3
2716 	while (len > 0) {
2717 		if (len < UMB_QMI_TLVLEN)
2718 			goto tooshort;
2719 		tlvlen = UMB_GET16(&data[1]);
2720 		if (len < UMB_QMI_TLVLEN + tlvlen)
2721 			goto tooshort;
2722 		switch (data[0]) {
2723 		case 1:	/* allocation info */
2724 			if (msg == 0x0022) {	/* Allocate CID */
2725 				if (tlvlen != 2 || data[3] != 2) /* dms */
2726 					break;
2727 				sc->sc_cid = data[4];
2728 				DPRINTF("QMI CID %d allocated\n",
2729 				    sc->sc_cid);
2730 				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
2731 			}
2732 			break;
2733 		case 2:	/* response */
2734 			if (tlvlen != sizeof (val))
2735 				break;
2736 			val = UMB_GET32(&data[3]);
2737 			switch (msg) {
2738 			case 0x0022:	/* Allocate CID */
2739 				if (val != 0) {
2740 					log(LOG_ERR, "%s: allocation of QMI CID"
2741 					    " failed, error 0x%x\n", DEVNAM(sc),
2742 					    val);
2743 					/* XXX how to proceed? */
2744 					return;
2745 				}
2746 				break;
2747 			case 0x555f:	/* Send FCC Authentication */
2748 				if (val == 0)
2749 					DPRINTF("%s: send FCC "
2750 					    "Authentication succeeded\n",
2751 					    DEVNAM(sc));
2752 				else if (val == 0x001a0001)
2753 					DPRINTF("%s: FCC Authentication "
2754 					    "not required\n", DEVNAM(sc));
2755 				else
2756 					log(LOG_INFO, "%s: send FCC "
2757 					    "Authentication failed, "
2758 					    "error 0x%x\n", DEVNAM(sc), val);
2759 
2760 				/* FCC Auth is needed only once after power-on*/
2761 				sc->sc_flags &= ~UMBFLG_FCC_AUTH_REQUIRED;
2762 
2763 				/* Try to proceed anyway */
2764 				DPRINTF("init: turning radio on ...\n");
2765 				umb_radio(sc, 1);
2766 				break;
2767 			default:
2768 				break;
2769 			}
2770 			break;
2771 		default:
2772 			break;
2773 		}
2774 		data += UMB_QMI_TLVLEN + tlvlen;
2775 		len -= UMB_QMI_TLVLEN + tlvlen;
2776 	}
2777 	return;
2778 
2779 tooshort:
2780 	DPRINTF("discard short QMI message\n");
2781 	return;
2782 }
2783 
2784 static void
umb_intr(struct usb_xfer * xfer,usb_error_t status)2785 umb_intr(struct usb_xfer *xfer, usb_error_t status)
2786 {
2787 	struct umb_softc *sc = usbd_xfer_softc(xfer);
2788 	struct usb_cdc_notification notification;
2789 	struct usb_page_cache *pc;
2790 	if_t ifp = GET_IFP(sc);
2791 	int	 total_len;
2792 
2793 	mtx_assert(&sc->sc_mutex, MA_OWNED);
2794 
2795 	/* FIXME use actlen or total_len? */
2796 	usbd_xfer_status(xfer, &total_len, NULL, NULL, NULL);
2797 
2798 	switch (USB_GET_STATE(xfer)) {
2799 	case USB_ST_TRANSFERRED:
2800 		DPRINTF("Received %d bytes\n", total_len);
2801 
2802 		if (total_len < UCDC_NOTIFICATION_LENGTH) {
2803 			DPRINTF("short notification (%d<%d)\n",
2804 					total_len, UCDC_NOTIFICATION_LENGTH);
2805 			return;
2806 		}
2807 
2808 		pc = usbd_xfer_get_frame(xfer, 0);
2809 		usbd_copy_out(pc, 0, &notification, sizeof (notification));
2810 
2811 		if (notification.bmRequestType != UCDC_NOTIFICATION) {
2812 			DPRINTF("unexpected notification (type=0x%02x)\n",
2813 					notification.bmRequestType);
2814 			return;
2815 		}
2816 
2817 		switch (notification.bNotification) {
2818 		case UCDC_N_NETWORK_CONNECTION:
2819 			if (if_getflags(ifp) & IFF_DEBUG)
2820 				log(LOG_DEBUG, "%s: network %sconnected\n",
2821 						DEVNAM(sc),
2822 						UGETW(notification.wValue)
2823 						? "" : "dis");
2824 			break;
2825 		case UCDC_N_RESPONSE_AVAILABLE:
2826 			DPRINTFN(2, "umb_intr: response available\n");
2827 			++sc->sc_nresp;
2828 			umb_add_task(sc, umb_get_response_task,
2829 					&sc->sc_proc_get_response_task[0].hdr,
2830 					&sc->sc_proc_get_response_task[1].hdr,
2831 					0);
2832 			break;
2833 		case UCDC_N_CONNECTION_SPEED_CHANGE:
2834 			DPRINTFN(2, "umb_intr: connection speed changed\n");
2835 			break;
2836 		default:
2837 			DPRINTF("unexpected notification (0x%02x)\n",
2838 					notification.bNotification);
2839 			break;
2840 		}
2841 		/* fallthrough */
2842 	case USB_ST_SETUP:
2843 tr_setup:
2844 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
2845 		usbd_transfer_submit(xfer);
2846 		break;
2847 	default:
2848 		if (status != USB_ERR_CANCELLED) {
2849 			/* start clear stall */
2850 			usbd_xfer_set_stall(xfer);
2851 			goto tr_setup;
2852 		}
2853 		break;
2854 	}
2855 }
2856 
2857 /*
2858  * Diagnostic routines
2859  */
2860 static char *
umb_ntop(struct sockaddr * sa)2861 umb_ntop(struct sockaddr *sa)
2862 {
2863 #define NUMBUFS		4
2864 	static char astr[NUMBUFS][INET_ADDRSTRLEN];
2865 	static unsigned nbuf = 0;
2866 	char	*s;
2867 
2868 	s = astr[nbuf++];
2869 	if (nbuf >= NUMBUFS)
2870 		nbuf = 0;
2871 
2872 	switch (sa->sa_family) {
2873 	case AF_INET:
2874 	default:
2875 		inet_ntop(AF_INET, &satosin(sa)->sin_addr, s, sizeof (astr[0]));
2876 		break;
2877 	case AF_INET6:
2878 		inet_ntop(AF_INET6, &satosin6(sa)->sin6_addr, s,
2879 		    sizeof (astr[0]));
2880 		break;
2881 	}
2882 	return s;
2883 }
2884 
2885 #ifdef UMB_DEBUG
2886 static char *
umb_uuid2str(uint8_t uuid[MBIM_UUID_LEN])2887 umb_uuid2str(uint8_t uuid[MBIM_UUID_LEN])
2888 {
2889 	static char uuidstr[2 * MBIM_UUID_LEN + 5];
2890 
2891 #define UUID_BFMT	"%02X"
2892 #define UUID_SEP	"-"
2893 	snprintf(uuidstr, sizeof (uuidstr),
2894 	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_SEP
2895 	    UUID_BFMT UUID_BFMT UUID_SEP
2896 	    UUID_BFMT UUID_BFMT UUID_SEP
2897 	    UUID_BFMT UUID_BFMT UUID_SEP
2898 	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT,
2899 	    uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
2900 	    uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
2901 	    uuid[12], uuid[13], uuid[14], uuid[15]);
2902 	return uuidstr;
2903 }
2904 
2905 static void
umb_dump(void * buf,int len)2906 umb_dump(void *buf, int len)
2907 {
2908 	int	 i = 0;
2909 	uint8_t	*c = buf;
2910 
2911 	if (len == 0)
2912 		return;
2913 	while (i < len) {
2914 		if ((i % 16) == 0) {
2915 			if (i > 0)
2916 				log(LOG_DEBUG, "\n");
2917 			log(LOG_DEBUG, "%4d:  ", i);
2918 		}
2919 		log(LOG_DEBUG, " %02x", *c);
2920 		c++;
2921 		i++;
2922 	}
2923 	log(LOG_DEBUG, "\n");
2924 }
2925 #endif /* UMB_DEBUG */
2926 
2927 DRIVER_MODULE(umb, uhub, umb_driver, NULL, NULL);
2928 MODULE_DEPEND(umb, usb, 1, 1, 1);
2929