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