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, ¬ification, 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