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 if (inlen >= offs + sz) {
1381 memset(out, 0, outlen);
1382 memcpy(out, in + offs, MIN(sz, outlen));
1383 }
1384 }
1385
1386 static inline int
umb_padding(void * data,int len,size_t sz)1387 umb_padding(void *data, int len, size_t sz)
1388 {
1389 char *p = data;
1390 int np = 0;
1391
1392 while (len < sz && (len % 4) != 0) {
1393 *p++ = '\0';
1394 len++;
1395 np++;
1396 }
1397 return np;
1398 }
1399
1400 static inline int
umb_addstr(void * buf,size_t bufsz,int * offs,void * str,int slen,uint32_t * offsmember,uint32_t * sizemember)1401 umb_addstr(void *buf, size_t bufsz, int *offs, void *str, int slen,
1402 uint32_t *offsmember, uint32_t *sizemember)
1403 {
1404 if (*offs + slen > bufsz)
1405 return 0;
1406
1407 *sizemember = htole32((uint32_t)slen);
1408 if (slen && str) {
1409 *offsmember = htole32((uint32_t)*offs);
1410 memcpy((char *)buf + *offs, str, slen);
1411 *offs += slen;
1412 *offs += umb_padding(buf, *offs, bufsz);
1413 } else
1414 *offsmember = htole32(0);
1415 return 1;
1416 }
1417
1418 static void
umb_in_len2mask(struct in_addr * mask,int len)1419 umb_in_len2mask(struct in_addr *mask, int len)
1420 {
1421 int i;
1422 u_char *p;
1423
1424 p = (u_char *)mask;
1425 memset(mask, 0, sizeof (*mask));
1426 for (i = 0; i < len / 8; i++)
1427 p[i] = 0xff;
1428 if (len % 8)
1429 p[i] = (0xff00 >> (len % 8)) & 0xff;
1430 }
1431
1432 static int
umb_decode_register_state(struct umb_softc * sc,void * data,int len)1433 umb_decode_register_state(struct umb_softc *sc, void *data, int len)
1434 {
1435 struct mbim_cid_registration_state_info *rs = data;
1436 if_t ifp = GET_IFP(sc);
1437
1438 if (len < sizeof (*rs))
1439 return 0;
1440 sc->sc_info.nwerror = le32toh(rs->nwerror);
1441 sc->sc_info.regstate = le32toh(rs->regstate);
1442 sc->sc_info.regmode = le32toh(rs->regmode);
1443 sc->sc_info.cellclass = le32toh(rs->curcellclass);
1444
1445 /* XXX should we remember the provider_id? */
1446 umb_getinfobuf(data, len, rs->provname_offs, rs->provname_size,
1447 sc->sc_info.provider, sizeof (sc->sc_info.provider));
1448 umb_getinfobuf(data, len, rs->roamingtxt_offs, rs->roamingtxt_size,
1449 sc->sc_info.roamingtxt, sizeof (sc->sc_info.roamingtxt));
1450
1451 DPRINTFN(2, "%s, availclass 0x%x, class 0x%x, regmode %d\n",
1452 umb_regstate(sc->sc_info.regstate),
1453 le32toh(rs->availclasses), sc->sc_info.cellclass,
1454 sc->sc_info.regmode);
1455
1456 if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING &&
1457 !sc->sc_roaming &&
1458 sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED) {
1459 if (if_getflags(ifp) & IFF_DEBUG)
1460 log(LOG_INFO,
1461 "%s: disconnecting from roaming network\n",
1462 DEVNAM(sc));
1463 umb_disconnect(sc);
1464 }
1465 return 1;
1466 }
1467
1468 static int
umb_decode_devices_caps(struct umb_softc * sc,void * data,int len)1469 umb_decode_devices_caps(struct umb_softc *sc, void *data, int len)
1470 {
1471 struct mbim_cid_device_caps *dc = data;
1472
1473 if (len < sizeof (*dc))
1474 return 0;
1475 sc->sc_maxsessions = le32toh(dc->max_sessions);
1476 sc->sc_info.supportedclasses = le32toh(dc->dataclass);
1477 umb_getinfobuf(data, len, dc->devid_offs, dc->devid_size,
1478 sc->sc_info.devid, sizeof (sc->sc_info.devid));
1479 umb_getinfobuf(data, len, dc->fwinfo_offs, dc->fwinfo_size,
1480 sc->sc_info.fwinfo, sizeof (sc->sc_info.fwinfo));
1481 umb_getinfobuf(data, len, dc->hwinfo_offs, dc->hwinfo_size,
1482 sc->sc_info.hwinfo, sizeof (sc->sc_info.hwinfo));
1483 DPRINTFN(2, "max sessions %d, supported classes 0x%x\n",
1484 sc->sc_maxsessions, sc->sc_info.supportedclasses);
1485 return 1;
1486 }
1487
1488 static int
umb_decode_subscriber_status(struct umb_softc * sc,void * data,int len)1489 umb_decode_subscriber_status(struct umb_softc *sc, void *data, int len)
1490 {
1491 struct mbim_cid_subscriber_ready_info *si = data;
1492 if_t ifp = GET_IFP(sc);
1493 int npn;
1494
1495 if (len < sizeof (*si))
1496 return 0;
1497 sc->sc_info.sim_state = le32toh(si->ready);
1498
1499 umb_getinfobuf(data, len, si->sid_offs, si->sid_size,
1500 sc->sc_info.sid, sizeof (sc->sc_info.sid));
1501 umb_getinfobuf(data, len, si->icc_offs, si->icc_size,
1502 sc->sc_info.iccid, sizeof (sc->sc_info.iccid));
1503
1504 npn = le32toh(si->no_pn);
1505 if (npn > 0)
1506 umb_getinfobuf(data, len, si->pn[0].offs, si->pn[0].size,
1507 sc->sc_info.pn, sizeof (sc->sc_info.pn));
1508 else
1509 memset(sc->sc_info.pn, 0, sizeof (sc->sc_info.pn));
1510
1511 if (sc->sc_info.sim_state == MBIM_SIMSTATE_LOCKED)
1512 sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1513 if (if_getflags(ifp) & IFF_DEBUG)
1514 log(LOG_INFO, "%s: SIM %s\n", DEVNAM(sc),
1515 umb_simstate(sc->sc_info.sim_state));
1516 if (sc->sc_info.sim_state == MBIM_SIMSTATE_INITIALIZED)
1517 umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_DROP);
1518 return 1;
1519 }
1520
1521 static int
umb_decode_radio_state(struct umb_softc * sc,void * data,int len)1522 umb_decode_radio_state(struct umb_softc *sc, void *data, int len)
1523 {
1524 struct mbim_cid_radio_state_info *rs = data;
1525 if_t ifp = GET_IFP(sc);
1526
1527 if (len < sizeof (*rs))
1528 return 0;
1529
1530 sc->sc_info.hw_radio_on =
1531 (le32toh(rs->hw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1532 sc->sc_info.sw_radio_on =
1533 (le32toh(rs->sw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1534 if (!sc->sc_info.hw_radio_on) {
1535 device_printf(sc->sc_dev, "radio is disabled by hardware switch\n");
1536 /*
1537 * XXX do we need a time to poll the state of the rfkill switch
1538 * or will the device send an unsolicited notification
1539 * in case the state changes?
1540 */
1541 umb_newstate(sc, UMB_S_OPEN, 0);
1542 } else if (!sc->sc_info.sw_radio_on) {
1543 if (if_getflags(ifp) & IFF_DEBUG)
1544 log(LOG_INFO, "%s: radio is off\n", DEVNAM(sc));
1545 umb_newstate(sc, UMB_S_OPEN, 0);
1546 } else
1547 umb_newstate(sc, UMB_S_RADIO, UMB_NS_DONT_DROP);
1548 return 1;
1549 }
1550
1551 static int
umb_decode_pin(struct umb_softc * sc,void * data,int len)1552 umb_decode_pin(struct umb_softc *sc, void *data, int len)
1553 {
1554 struct mbim_cid_pin_info *pi = data;
1555 if_t ifp = GET_IFP(sc);
1556 uint32_t attempts_left;
1557
1558 if (len < sizeof (*pi))
1559 return 0;
1560
1561 attempts_left = le32toh(pi->remaining_attempts);
1562 if (attempts_left != 0xffffffff)
1563 sc->sc_info.pin_attempts_left = attempts_left;
1564
1565 switch (le32toh(pi->state)) {
1566 case MBIM_PIN_STATE_UNLOCKED:
1567 sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1568 break;
1569 case MBIM_PIN_STATE_LOCKED:
1570 switch (le32toh(pi->type)) {
1571 case MBIM_PIN_TYPE_PIN1:
1572 sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1573 break;
1574 case MBIM_PIN_TYPE_PUK1:
1575 sc->sc_info.pin_state = UMB_PUK_REQUIRED;
1576 break;
1577 case MBIM_PIN_TYPE_PIN2:
1578 case MBIM_PIN_TYPE_PUK2:
1579 /* Assume that PIN1 was accepted */
1580 sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1581 break;
1582 }
1583 break;
1584 }
1585 if (if_getflags(ifp) & IFF_DEBUG)
1586 log(LOG_INFO, "%s: %s state %s (%d attempts left)\n",
1587 DEVNAM(sc), umb_pin_type(le32toh(pi->type)),
1588 (le32toh(pi->state) == MBIM_PIN_STATE_UNLOCKED) ?
1589 "unlocked" : "locked",
1590 le32toh(pi->remaining_attempts));
1591
1592 /*
1593 * In case the PIN was set after IFF_UP, retrigger the state machine
1594 */
1595 umb_add_task(sc, umb_state_task,
1596 &sc->sc_proc_state_task[0].hdr,
1597 &sc->sc_proc_state_task[1].hdr, 0);
1598 return 1;
1599 }
1600
1601 static int
umb_decode_packet_service(struct umb_softc * sc,void * data,int len)1602 umb_decode_packet_service(struct umb_softc *sc, void *data, int len)
1603 {
1604 struct mbim_cid_packet_service_info *psi = data;
1605 int state, highestclass;
1606 uint64_t up_speed, down_speed;
1607 if_t ifp = GET_IFP(sc);
1608
1609 if (len < sizeof (*psi))
1610 return 0;
1611
1612 sc->sc_info.nwerror = le32toh(psi->nwerror);
1613 state = le32toh(psi->state);
1614 highestclass = le32toh(psi->highest_dataclass);
1615 up_speed = le64toh(psi->uplink_speed);
1616 down_speed = le64toh(psi->downlink_speed);
1617 if (sc->sc_info.packetstate != state ||
1618 sc->sc_info.uplink_speed != up_speed ||
1619 sc->sc_info.downlink_speed != down_speed) {
1620 if (if_getflags(ifp) & IFF_DEBUG) {
1621 log(LOG_INFO, "%s: packet service ", DEVNAM(sc));
1622 if (sc->sc_info.packetstate != state)
1623 log(LOG_INFO, "changed from %s to ",
1624 umb_packet_state(sc->sc_info.packetstate));
1625 log(LOG_INFO, "%s, class %s, speed: %" PRIu64 " up / %" PRIu64 " down\n",
1626 umb_packet_state(state),
1627 umb_dataclass(highestclass), up_speed, down_speed);
1628 }
1629 }
1630 sc->sc_info.packetstate = state;
1631 sc->sc_info.highestclass = highestclass;
1632 sc->sc_info.uplink_speed = up_speed;
1633 sc->sc_info.downlink_speed = down_speed;
1634
1635 if (sc->sc_info.regmode == MBIM_REGMODE_AUTOMATIC) {
1636 /*
1637 * For devices using automatic registration mode, just proceed,
1638 * once registration has completed.
1639 */
1640 if (if_getflags(ifp) & IFF_UP) {
1641 switch (sc->sc_info.regstate) {
1642 case MBIM_REGSTATE_HOME:
1643 case MBIM_REGSTATE_ROAMING:
1644 case MBIM_REGSTATE_PARTNER:
1645 umb_newstate(sc, UMB_S_ATTACHED,
1646 UMB_NS_DONT_DROP);
1647 break;
1648 default:
1649 break;
1650 }
1651 } else
1652 umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1653 } else switch (sc->sc_info.packetstate) {
1654 case MBIM_PKTSERVICE_STATE_ATTACHED:
1655 umb_newstate(sc, UMB_S_ATTACHED, UMB_NS_DONT_DROP);
1656 break;
1657 case MBIM_PKTSERVICE_STATE_DETACHED:
1658 umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1659 break;
1660 }
1661 return 1;
1662 }
1663
1664 static int
umb_decode_signal_state(struct umb_softc * sc,void * data,int len)1665 umb_decode_signal_state(struct umb_softc *sc, void *data, int len)
1666 {
1667 struct mbim_cid_signal_state *ss = data;
1668 if_t ifp = GET_IFP(sc);
1669 int rssi;
1670
1671 if (len < sizeof (*ss))
1672 return 0;
1673
1674 if (le32toh(ss->rssi) == 99)
1675 rssi = UMB_VALUE_UNKNOWN;
1676 else {
1677 rssi = -113 + 2 * le32toh(ss->rssi);
1678 if ((if_getflags(ifp) & IFF_DEBUG) && sc->sc_info.rssi != rssi &&
1679 sc->sc_state >= UMB_S_CONNECTED)
1680 log(LOG_INFO, "%s: rssi %d dBm\n", DEVNAM(sc), rssi);
1681 }
1682 sc->sc_info.rssi = rssi;
1683 sc->sc_info.ber = le32toh(ss->err_rate);
1684 if (sc->sc_info.ber == -99)
1685 sc->sc_info.ber = UMB_VALUE_UNKNOWN;
1686 return 1;
1687 }
1688
1689 static int
umb_decode_connect_info(struct umb_softc * sc,void * data,int len)1690 umb_decode_connect_info(struct umb_softc *sc, void *data, int len)
1691 {
1692 struct mbim_cid_connect_info *ci = data;
1693 if_t ifp = GET_IFP(sc);
1694 int act;
1695
1696 if (len < sizeof (*ci))
1697 return 0;
1698
1699 if (le32toh(ci->sessionid) != umb_session_id) {
1700 DPRINTF("discard connection info for session %u\n",
1701 le32toh(ci->sessionid));
1702 return 1;
1703 }
1704 if (memcmp(ci->context, umb_uuid_context_internet,
1705 sizeof (ci->context))) {
1706 DPRINTF("discard connection info for other context\n");
1707 return 1;
1708 }
1709 act = le32toh(ci->activation);
1710 if (sc->sc_info.activation != act) {
1711 if (if_getflags(ifp) & IFF_DEBUG)
1712 log(LOG_INFO, "%s: connection %s\n", DEVNAM(sc),
1713 umb_activation(act));
1714 if ((if_getflags(ifp) & IFF_DEBUG) &&
1715 le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_DEFAULT &&
1716 le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_IPV4)
1717 log(LOG_DEBUG, "%s: got iptype %d connection\n",
1718 DEVNAM(sc), le32toh(ci->iptype));
1719
1720 sc->sc_info.activation = act;
1721 sc->sc_info.nwerror = le32toh(ci->nwerror);
1722
1723 if (sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED)
1724 umb_newstate(sc, UMB_S_CONNECTED, UMB_NS_DONT_DROP);
1725 else if (sc->sc_info.activation ==
1726 MBIM_ACTIVATION_STATE_DEACTIVATED)
1727 umb_newstate(sc, UMB_S_ATTACHED, 0);
1728 /* else: other states are purely transitional */
1729 }
1730 return 1;
1731 }
1732
1733 static int
umb_add_inet_config(struct umb_softc * sc,struct in_addr ip,u_int prefixlen,struct in_addr gw)1734 umb_add_inet_config(struct umb_softc *sc, struct in_addr ip, u_int prefixlen,
1735 struct in_addr gw)
1736 {
1737 if_t ifp = GET_IFP(sc);
1738 struct in_aliasreq ifra;
1739 struct sockaddr_in *sin;
1740 int rv;
1741
1742 memset(&ifra, 0, sizeof (ifra));
1743 sin = (struct sockaddr_in *)&ifra.ifra_addr;
1744 sin->sin_family = AF_INET;
1745 sin->sin_len = sizeof (*sin);
1746 sin->sin_addr = ip;
1747
1748 sin = (struct sockaddr_in *)&ifra.ifra_dstaddr;
1749 sin->sin_family = AF_INET;
1750 sin->sin_len = sizeof (*sin);
1751 sin->sin_addr = gw;
1752
1753 sin = (struct sockaddr_in *)&ifra.ifra_mask;
1754 sin->sin_family = AF_INET;
1755 sin->sin_len = sizeof (*sin);
1756 umb_in_len2mask(&sin->sin_addr, prefixlen);
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 ptr16 = (struct ncm_pointer16 *)(buf + ptroff);
2151 psig = UGETDW(ptr16->dwSignature);
2152 ptrlen = UGETW(ptr16->wLength);
2153 if (len < ptrlen + ptroff)
2154 goto toosmall;
2155 if (!MBIM_NCM_NTH16_ISISG(psig) && !MBIM_NCM_NTH32_ISISG(psig)) {
2156 DPRINTF("%s: unsupported NCM pointer signature (0x%08x)\n",
2157 DEVNAM(sc), psig);
2158 goto fail;
2159 }
2160
2161 switch (hsig) {
2162 case NCM_HDR16_SIG:
2163 dgentryoff = offsetof(struct ncm_pointer16, dgram);
2164 break;
2165 case NCM_HDR32_SIG:
2166 dgentryoff = offsetof(struct ncm_pointer32, dgram);
2167 break;
2168 default:
2169 goto fail;
2170 }
2171
2172 while (dgentryoff < ptrlen) {
2173 switch (hsig) {
2174 case NCM_HDR16_SIG:
2175 if (ptroff + dgentryoff < sizeof (*dgram16))
2176 goto done;
2177 dgram16 = (struct ncm_pointer16_dgram *)
2178 (buf + ptroff + dgentryoff);
2179 dgentryoff += sizeof (*dgram16);
2180 dlen = UGETW(dgram16->wDatagramLen);
2181 doff = UGETW(dgram16->wDatagramIndex);
2182 break;
2183 case NCM_HDR32_SIG:
2184 if (ptroff + dgentryoff < sizeof (*dgram32))
2185 goto done;
2186 dgram32 = (struct ncm_pointer32_dgram *)
2187 (buf + ptroff + dgentryoff);
2188 dgentryoff += sizeof (*dgram32);
2189 dlen = UGETDW(dgram32->dwDatagramLen);
2190 doff = UGETDW(dgram32->dwDatagramIndex);
2191 break;
2192 default:
2193 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2194 goto done;
2195 }
2196
2197 /* Terminating zero entry */
2198 if (dlen == 0 || doff == 0)
2199 break;
2200 if (len < dlen + doff) {
2201 /* Skip giant datagram but continue processing */
2202 DPRINTF("%s: datagram too large (%d @ off %d)\n",
2203 DEVNAM(sc), dlen, doff);
2204 continue;
2205 }
2206
2207 dp = buf + doff;
2208 DPRINTFN(3, "%s: decap %d bytes\n", DEVNAM(sc), dlen);
2209 m = m_devget(dp, dlen, 0, ifp, NULL);
2210 if (m == NULL) {
2211 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2212 continue;
2213 }
2214
2215 /* enqueue for later when the lock can be released */
2216 _IF_ENQUEUE(&sc->sc_rx_queue, m);
2217
2218 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
2219
2220 }
2221 done:
2222 sc->sc_rx_nerr = 0;
2223 return;
2224 toosmall:
2225 DPRINTF("%s: packet too small (%d)\n", DEVNAM(sc), len);
2226 fail:
2227 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2228 }
2229
2230 static usb_error_t
umb_send_encap_command(struct umb_softc * sc,void * data,int len)2231 umb_send_encap_command(struct umb_softc *sc, void *data, int len)
2232 {
2233 usb_device_request_t req;
2234
2235 if (len > sc->sc_ctrl_len)
2236 return USB_ERR_INVAL;
2237
2238 /* XXX FIXME: if (total len > sc->sc_ctrl_len) => must fragment */
2239 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
2240 req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
2241 USETW(req.wValue, 0);
2242 USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2243 USETW(req.wLength, len);
2244 mtx_unlock(&sc->sc_mutex);
2245 DELAY(umb_delay);
2246 mtx_lock(&sc->sc_mutex);
2247 return usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, data, 0,
2248 NULL, umb_xfer_tout);
2249 }
2250
2251 static int
umb_get_encap_response(struct umb_softc * sc,void * buf,int * len)2252 umb_get_encap_response(struct umb_softc *sc, void *buf, int *len)
2253 {
2254 usb_device_request_t req;
2255 usb_error_t err;
2256 uint16_t l = *len;
2257
2258 req.bmRequestType = UT_READ_CLASS_INTERFACE;
2259 req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
2260 USETW(req.wValue, 0);
2261 USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2262 USETW(req.wLength, l);
2263 /* XXX FIXME: re-assemble fragments */
2264
2265 mtx_unlock(&sc->sc_mutex);
2266 DELAY(umb_delay);
2267 mtx_lock(&sc->sc_mutex);
2268 err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, buf,
2269 USB_SHORT_XFER_OK, &l, umb_xfer_tout);
2270 if (err == USB_ERR_NORMAL_COMPLETION) {
2271 *len = l;
2272 return 1;
2273 }
2274 DPRINTF("ctrl recv: %s\n", usbd_errstr(err));
2275 return 0;
2276 }
2277
2278 static void
umb_ctrl_msg(struct umb_softc * sc,uint32_t req,void * data,int len)2279 umb_ctrl_msg(struct umb_softc *sc, uint32_t req, void *data, int len)
2280 {
2281 if_t ifp = GET_IFP(sc);
2282 uint32_t tid;
2283 struct mbim_msghdr *hdr = data;
2284 usb_error_t err;
2285
2286 if (sc->sc_dying)
2287 return;
2288 if (len < sizeof (*hdr))
2289 return;
2290 tid = ++sc->sc_tid;
2291
2292 hdr->type = htole32(req);
2293 hdr->len = htole32(len);
2294 hdr->tid = htole32(tid);
2295
2296 #ifdef UMB_DEBUG
2297 if (umb_debug) {
2298 const char *op, *str;
2299 if (req == MBIM_COMMAND_MSG) {
2300 struct mbim_h2f_cmd *c = data;
2301 if (le32toh(c->op) == MBIM_CMDOP_SET)
2302 op = "set";
2303 else
2304 op = "qry";
2305 str = umb_cid2str(le32toh(c->cid));
2306 } else {
2307 op = "snd";
2308 str = umb_request2str(req);
2309 }
2310 DPRINTF("-> %s %s (tid %u)\n", op, str, tid);
2311 }
2312 #endif
2313 err = umb_send_encap_command(sc, data, len);
2314 if (err != USB_ERR_NORMAL_COMPLETION) {
2315 if (if_getflags(ifp) & IFF_DEBUG)
2316 log(LOG_ERR, "%s: send %s msg (tid %u) failed: %s\n",
2317 DEVNAM(sc), umb_request2str(req), tid,
2318 usbd_errstr(err));
2319
2320 /* will affect other transactions, too */
2321 usbd_transfer_stop(sc->sc_xfer[UMB_INTR_RX]);
2322 } else {
2323 DPRINTFN(2, "sent %s (tid %u)\n",
2324 umb_request2str(req), tid);
2325 DDUMPN(3, data, len);
2326 }
2327 return;
2328 }
2329
2330 static void
umb_open(struct umb_softc * sc)2331 umb_open(struct umb_softc *sc)
2332 {
2333 struct mbim_h2f_openmsg msg;
2334
2335 memset(&msg, 0, sizeof (msg));
2336 msg.maxlen = htole32(sc->sc_ctrl_len);
2337 umb_ctrl_msg(sc, MBIM_OPEN_MSG, &msg, sizeof (msg));
2338 return;
2339 }
2340
2341 static void
umb_close(struct umb_softc * sc)2342 umb_close(struct umb_softc *sc)
2343 {
2344 struct mbim_h2f_closemsg msg;
2345
2346 memset(&msg, 0, sizeof (msg));
2347 umb_ctrl_msg(sc, MBIM_CLOSE_MSG, &msg, sizeof (msg));
2348 }
2349
2350 static int
umb_setpin(struct umb_softc * sc,int op,int is_puk,void * pin,int pinlen,void * newpin,int newpinlen)2351 umb_setpin(struct umb_softc *sc, int op, int is_puk, void *pin, int pinlen,
2352 void *newpin, int newpinlen)
2353 {
2354 struct mbim_cid_pin cp;
2355 int off;
2356
2357 if (pinlen == 0)
2358 return 0;
2359 if (pinlen < 0 || pinlen > MBIM_PIN_MAXLEN ||
2360 newpinlen < 0 || newpinlen > MBIM_PIN_MAXLEN ||
2361 op < 0 || op > MBIM_PIN_OP_CHANGE ||
2362 (is_puk && op != MBIM_PIN_OP_ENTER))
2363 return EINVAL;
2364
2365 memset(&cp, 0, sizeof (cp));
2366 cp.type = htole32(is_puk ? MBIM_PIN_TYPE_PUK1 : MBIM_PIN_TYPE_PIN1);
2367
2368 off = offsetof(struct mbim_cid_pin, data);
2369 if (!umb_addstr(&cp, sizeof (cp), &off, pin, pinlen,
2370 &cp.pin_offs, &cp.pin_size))
2371 return EINVAL;
2372
2373 cp.op = htole32(op);
2374 if (newpinlen) {
2375 if (!umb_addstr(&cp, sizeof (cp), &off, newpin, newpinlen,
2376 &cp.newpin_offs, &cp.newpin_size))
2377 return EINVAL;
2378 } else {
2379 if ((op == MBIM_PIN_OP_CHANGE) || is_puk)
2380 return EINVAL;
2381 if (!umb_addstr(&cp, sizeof (cp), &off, NULL, 0,
2382 &cp.newpin_offs, &cp.newpin_size))
2383 return EINVAL;
2384 }
2385 mtx_lock(&sc->sc_mutex);
2386 umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_SET, &cp, off);
2387 mtx_unlock(&sc->sc_mutex);
2388 return 0;
2389 }
2390
2391 static void
umb_setdataclass(struct umb_softc * sc)2392 umb_setdataclass(struct umb_softc *sc)
2393 {
2394 struct mbim_cid_registration_state rs;
2395 uint32_t classes;
2396
2397 if (sc->sc_info.supportedclasses == MBIM_DATACLASS_NONE)
2398 return;
2399
2400 memset(&rs, 0, sizeof (rs));
2401 rs.regaction = htole32(MBIM_REGACTION_AUTOMATIC);
2402 classes = sc->sc_info.supportedclasses;
2403 if (sc->sc_info.preferredclasses != MBIM_DATACLASS_NONE)
2404 classes &= sc->sc_info.preferredclasses;
2405 rs.data_class = htole32(classes);
2406 mtx_lock(&sc->sc_mutex);
2407 umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_SET, &rs, sizeof (rs));
2408 mtx_unlock(&sc->sc_mutex);
2409 }
2410
2411 static void
umb_radio(struct umb_softc * sc,int on)2412 umb_radio(struct umb_softc *sc, int on)
2413 {
2414 struct mbim_cid_radio_state s;
2415
2416 DPRINTF("set radio %s\n", on ? "on" : "off");
2417 memset(&s, 0, sizeof (s));
2418 s.state = htole32(on ? MBIM_RADIO_STATE_ON : MBIM_RADIO_STATE_OFF);
2419 umb_cmd(sc, MBIM_CID_RADIO_STATE, MBIM_CMDOP_SET, &s, sizeof (s));
2420 }
2421
2422 static void
umb_allocate_cid(struct umb_softc * sc)2423 umb_allocate_cid(struct umb_softc *sc)
2424 {
2425 umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2426 umb_qmi_alloc_cid, sizeof (umb_qmi_alloc_cid), umb_uuid_qmi_mbim);
2427 }
2428
2429 static void
umb_send_fcc_auth(struct umb_softc * sc)2430 umb_send_fcc_auth(struct umb_softc *sc)
2431 {
2432 uint8_t fccauth[sizeof (umb_qmi_fcc_auth)];
2433
2434 if (sc->sc_cid == -1) {
2435 DPRINTF("missing CID, cannot send FCC auth\n");
2436 umb_allocate_cid(sc);
2437 return;
2438 }
2439 memcpy(fccauth, umb_qmi_fcc_auth, sizeof (fccauth));
2440 fccauth[UMB_QMI_CID_OFFS] = sc->sc_cid;
2441 umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2442 fccauth, sizeof (fccauth), umb_uuid_qmi_mbim);
2443 }
2444
2445 static void
umb_packet_service(struct umb_softc * sc,int attach)2446 umb_packet_service(struct umb_softc *sc, int attach)
2447 {
2448 struct mbim_cid_packet_service s;
2449
2450 DPRINTF("%s packet service\n",
2451 attach ? "attach" : "detach");
2452 memset(&s, 0, sizeof (s));
2453 s.action = htole32(attach ?
2454 MBIM_PKTSERVICE_ACTION_ATTACH : MBIM_PKTSERVICE_ACTION_DETACH);
2455 umb_cmd(sc, MBIM_CID_PACKET_SERVICE, MBIM_CMDOP_SET, &s, sizeof (s));
2456 }
2457
2458 static void
umb_connect(struct umb_softc * sc)2459 umb_connect(struct umb_softc *sc)
2460 {
2461 if_t ifp = GET_IFP(sc);
2462
2463 if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
2464 log(LOG_INFO, "%s: connection disabled in roaming network\n",
2465 DEVNAM(sc));
2466 return;
2467 }
2468 if (if_getflags(ifp) & IFF_DEBUG)
2469 log(LOG_DEBUG, "%s: connecting ...\n", DEVNAM(sc));
2470 umb_send_connect(sc, MBIM_CONNECT_ACTIVATE);
2471 }
2472
2473 static void
umb_disconnect(struct umb_softc * sc)2474 umb_disconnect(struct umb_softc *sc)
2475 {
2476 if_t ifp = GET_IFP(sc);
2477
2478 if (if_getflags(ifp) & IFF_DEBUG)
2479 log(LOG_DEBUG, "%s: disconnecting ...\n", DEVNAM(sc));
2480 umb_send_connect(sc, MBIM_CONNECT_DEACTIVATE);
2481 }
2482
2483 static void
umb_send_connect(struct umb_softc * sc,int command)2484 umb_send_connect(struct umb_softc *sc, int command)
2485 {
2486 struct mbim_cid_connect *c;
2487 int off;
2488
2489 /* Too large for the stack */
2490 mtx_unlock(&sc->sc_mutex);
2491 c = malloc(sizeof (*c), M_MBIM_CID_CONNECT, M_WAITOK | M_ZERO);
2492 mtx_lock(&sc->sc_mutex);
2493 c->sessionid = htole32(umb_session_id);
2494 c->command = htole32(command);
2495 off = offsetof(struct mbim_cid_connect, data);
2496 if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.apn,
2497 sc->sc_info.apnlen, &c->access_offs, &c->access_size))
2498 goto done;
2499 if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.username,
2500 sc->sc_info.usernamelen, &c->user_offs, &c->user_size))
2501 goto done;
2502 if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.password,
2503 sc->sc_info.passwordlen, &c->passwd_offs, &c->passwd_size))
2504 goto done;
2505 c->authprot = htole32(MBIM_AUTHPROT_NONE);
2506 c->compression = htole32(MBIM_COMPRESSION_NONE);
2507 c->iptype = htole32(MBIM_CONTEXT_IPTYPE_IPV4);
2508 memcpy(c->context, umb_uuid_context_internet, sizeof (c->context));
2509 umb_cmd(sc, MBIM_CID_CONNECT, MBIM_CMDOP_SET, c, off);
2510 done:
2511 free(c, M_MBIM_CID_CONNECT);
2512 return;
2513 }
2514
2515 static void
umb_qry_ipconfig(struct umb_softc * sc)2516 umb_qry_ipconfig(struct umb_softc *sc)
2517 {
2518 struct mbim_cid_ip_configuration_info ipc;
2519
2520 memset(&ipc, 0, sizeof (ipc));
2521 ipc.sessionid = htole32(umb_session_id);
2522 umb_cmd(sc, MBIM_CID_IP_CONFIGURATION, MBIM_CMDOP_QRY,
2523 &ipc, sizeof (ipc));
2524 }
2525
2526 static void
umb_cmd(struct umb_softc * sc,int cid,int op,const void * data,int len)2527 umb_cmd(struct umb_softc *sc, int cid, int op, const void *data, int len)
2528 {
2529 umb_cmd1(sc, cid, op, data, len, umb_uuid_basic_connect);
2530 }
2531
2532 static void
umb_cmd1(struct umb_softc * sc,int cid,int op,const void * data,int len,uint8_t * uuid)2533 umb_cmd1(struct umb_softc *sc, int cid, int op, const void *data, int len,
2534 uint8_t *uuid)
2535 {
2536 struct mbim_h2f_cmd *cmd;
2537 int totlen;
2538
2539 /* XXX FIXME support sending fragments */
2540 if (sizeof (*cmd) + len > sc->sc_ctrl_len) {
2541 DPRINTF("set %s msg too long: cannot send\n",
2542 umb_cid2str(cid));
2543 return;
2544 }
2545 cmd = sc->sc_ctrl_msg;
2546 memset(cmd, 0, sizeof (*cmd));
2547 cmd->frag.nfrag = htole32(1);
2548 memcpy(cmd->devid, uuid, sizeof (cmd->devid));
2549 cmd->cid = htole32(cid);
2550 cmd->op = htole32(op);
2551 cmd->infolen = htole32(len);
2552 totlen = sizeof (*cmd);
2553 if (len > 0) {
2554 memcpy(cmd + 1, data, len);
2555 totlen += len;
2556 }
2557 umb_ctrl_msg(sc, MBIM_COMMAND_MSG, cmd, totlen);
2558 }
2559
2560 static void
umb_command_done(struct umb_softc * sc,void * data,int len)2561 umb_command_done(struct umb_softc *sc, void *data, int len)
2562 {
2563 struct mbim_f2h_cmddone *cmd = data;
2564 if_t ifp = GET_IFP(sc);
2565 uint32_t status;
2566 uint32_t cid;
2567 uint32_t infolen;
2568 int qmimsg = 0;
2569
2570 if (len < sizeof (*cmd)) {
2571 DPRINTF("discard short %s message\n",
2572 umb_request2str(le32toh(cmd->hdr.type)));
2573 return;
2574 }
2575 cid = le32toh(cmd->cid);
2576 if (memcmp(cmd->devid, umb_uuid_basic_connect, sizeof (cmd->devid))) {
2577 if (memcmp(cmd->devid, umb_uuid_qmi_mbim,
2578 sizeof (cmd->devid))) {
2579 DPRINTF("discard %s message for other UUID '%s'\n",
2580 umb_request2str(le32toh(cmd->hdr.type)),
2581 umb_uuid2str(cmd->devid));
2582 return;
2583 } else
2584 qmimsg = 1;
2585 }
2586
2587 status = le32toh(cmd->status);
2588 switch (status) {
2589 case MBIM_STATUS_SUCCESS:
2590 break;
2591 case MBIM_STATUS_NOT_INITIALIZED:
2592 if (if_getflags(ifp) & IFF_DEBUG)
2593 log(LOG_ERR, "%s: SIM not initialized (PIN missing)\n",
2594 DEVNAM(sc));
2595 return;
2596 case MBIM_STATUS_PIN_REQUIRED:
2597 sc->sc_info.pin_state = UMB_PIN_REQUIRED;
2598 /*FALLTHROUGH*/
2599 default:
2600 if (if_getflags(ifp) & IFF_DEBUG)
2601 log(LOG_ERR, "%s: set/qry %s failed: %s\n", DEVNAM(sc),
2602 umb_cid2str(cid), umb_status2str(status));
2603 return;
2604 }
2605
2606 infolen = le32toh(cmd->infolen);
2607 if (len < sizeof (*cmd) + infolen) {
2608 DPRINTF("discard truncated %s message (want %d, got %d)\n",
2609 umb_cid2str(cid),
2610 (int)sizeof (*cmd) + infolen, len);
2611 return;
2612 }
2613 if (qmimsg) {
2614 if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED)
2615 umb_decode_qmi(sc, cmd->info, infolen);
2616 } else {
2617 DPRINTFN(2, "set/qry %s done\n",
2618 umb_cid2str(cid));
2619 umb_decode_cid(sc, cid, cmd->info, infolen);
2620 }
2621 }
2622
2623 static void
umb_decode_cid(struct umb_softc * sc,uint32_t cid,void * data,int len)2624 umb_decode_cid(struct umb_softc *sc, uint32_t cid, void *data, int len)
2625 {
2626 int ok = 1;
2627
2628 switch (cid) {
2629 case MBIM_CID_DEVICE_CAPS:
2630 ok = umb_decode_devices_caps(sc, data, len);
2631 break;
2632 case MBIM_CID_SUBSCRIBER_READY_STATUS:
2633 ok = umb_decode_subscriber_status(sc, data, len);
2634 break;
2635 case MBIM_CID_RADIO_STATE:
2636 ok = umb_decode_radio_state(sc, data, len);
2637 break;
2638 case MBIM_CID_PIN:
2639 ok = umb_decode_pin(sc, data, len);
2640 break;
2641 case MBIM_CID_REGISTER_STATE:
2642 ok = umb_decode_register_state(sc, data, len);
2643 break;
2644 case MBIM_CID_PACKET_SERVICE:
2645 ok = umb_decode_packet_service(sc, data, len);
2646 break;
2647 case MBIM_CID_SIGNAL_STATE:
2648 ok = umb_decode_signal_state(sc, data, len);
2649 break;
2650 case MBIM_CID_CONNECT:
2651 ok = umb_decode_connect_info(sc, data, len);
2652 break;
2653 case MBIM_CID_IP_CONFIGURATION:
2654 ok = umb_decode_ip_configuration(sc, data, len);
2655 break;
2656 default:
2657 /*
2658 * Note: the above list is incomplete and only contains
2659 * mandatory CIDs from the BASIC_CONNECT set.
2660 * So alternate values are not unusual.
2661 */
2662 DPRINTFN(4, "ignore %s\n", umb_cid2str(cid));
2663 break;
2664 }
2665 if (!ok)
2666 DPRINTF("discard %s with bad info length %d\n",
2667 umb_cid2str(cid), len);
2668 return;
2669 }
2670
2671 static void
umb_decode_qmi(struct umb_softc * sc,uint8_t * data,int len)2672 umb_decode_qmi(struct umb_softc *sc, uint8_t *data, int len)
2673 {
2674 uint8_t srv;
2675 uint16_t msg, tlvlen;
2676 uint32_t val;
2677
2678 #define UMB_QMI_QMUXLEN 6
2679 if (len < UMB_QMI_QMUXLEN)
2680 goto tooshort;
2681
2682 srv = data[4];
2683 data += UMB_QMI_QMUXLEN;
2684 len -= UMB_QMI_QMUXLEN;
2685
2686 #define UMB_GET16(p) ((uint16_t)*p | (uint16_t)*(p + 1) << 8)
2687 #define UMB_GET32(p) ((uint32_t)*p | (uint32_t)*(p + 1) << 8 | \
2688 (uint32_t)*(p + 2) << 16 |(uint32_t)*(p + 3) << 24)
2689 switch (srv) {
2690 case 0: /* ctl */
2691 #define UMB_QMI_CTLLEN 6
2692 if (len < UMB_QMI_CTLLEN)
2693 goto tooshort;
2694 msg = UMB_GET16(&data[2]);
2695 tlvlen = UMB_GET16(&data[4]);
2696 data += UMB_QMI_CTLLEN;
2697 len -= UMB_QMI_CTLLEN;
2698 break;
2699 case 2: /* dms */
2700 #define UMB_QMI_DMSLEN 7
2701 if (len < UMB_QMI_DMSLEN)
2702 goto tooshort;
2703 msg = UMB_GET16(&data[3]);
2704 tlvlen = UMB_GET16(&data[5]);
2705 data += UMB_QMI_DMSLEN;
2706 len -= UMB_QMI_DMSLEN;
2707 break;
2708 default:
2709 DPRINTF("discard QMI message for unknown service type %d\n",
2710 srv);
2711 return;
2712 }
2713
2714 if (len < tlvlen)
2715 goto tooshort;
2716
2717 #define UMB_QMI_TLVLEN 3
2718 while (len > 0) {
2719 if (len < UMB_QMI_TLVLEN)
2720 goto tooshort;
2721 tlvlen = UMB_GET16(&data[1]);
2722 if (len < UMB_QMI_TLVLEN + tlvlen)
2723 goto tooshort;
2724 switch (data[0]) {
2725 case 1: /* allocation info */
2726 if (msg == 0x0022) { /* Allocate CID */
2727 if (tlvlen != 2 || data[3] != 2) /* dms */
2728 break;
2729 sc->sc_cid = data[4];
2730 DPRINTF("QMI CID %d allocated\n",
2731 sc->sc_cid);
2732 umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
2733 }
2734 break;
2735 case 2: /* response */
2736 if (tlvlen != sizeof (val))
2737 break;
2738 val = UMB_GET32(&data[3]);
2739 switch (msg) {
2740 case 0x0022: /* Allocate CID */
2741 if (val != 0) {
2742 log(LOG_ERR, "%s: allocation of QMI CID"
2743 " failed, error 0x%x\n", DEVNAM(sc),
2744 val);
2745 /* XXX how to proceed? */
2746 return;
2747 }
2748 break;
2749 case 0x555f: /* Send FCC Authentication */
2750 if (val == 0)
2751 DPRINTF("%s: send FCC "
2752 "Authentication succeeded\n",
2753 DEVNAM(sc));
2754 else if (val == 0x001a0001)
2755 DPRINTF("%s: FCC Authentication "
2756 "not required\n", DEVNAM(sc));
2757 else
2758 log(LOG_INFO, "%s: send FCC "
2759 "Authentication failed, "
2760 "error 0x%x\n", DEVNAM(sc), val);
2761
2762 /* FCC Auth is needed only once after power-on*/
2763 sc->sc_flags &= ~UMBFLG_FCC_AUTH_REQUIRED;
2764
2765 /* Try to proceed anyway */
2766 DPRINTF("init: turning radio on ...\n");
2767 umb_radio(sc, 1);
2768 break;
2769 default:
2770 break;
2771 }
2772 break;
2773 default:
2774 break;
2775 }
2776 data += UMB_QMI_TLVLEN + tlvlen;
2777 len -= UMB_QMI_TLVLEN + tlvlen;
2778 }
2779 return;
2780
2781 tooshort:
2782 DPRINTF("discard short QMI message\n");
2783 return;
2784 }
2785
2786 static void
umb_intr(struct usb_xfer * xfer,usb_error_t status)2787 umb_intr(struct usb_xfer *xfer, usb_error_t status)
2788 {
2789 struct umb_softc *sc = usbd_xfer_softc(xfer);
2790 struct usb_cdc_notification notification;
2791 struct usb_page_cache *pc;
2792 if_t ifp = GET_IFP(sc);
2793 int total_len;
2794
2795 mtx_assert(&sc->sc_mutex, MA_OWNED);
2796
2797 /* FIXME use actlen or total_len? */
2798 usbd_xfer_status(xfer, &total_len, NULL, NULL, NULL);
2799
2800 switch (USB_GET_STATE(xfer)) {
2801 case USB_ST_TRANSFERRED:
2802 DPRINTF("Received %d bytes\n", total_len);
2803
2804 if (total_len < UCDC_NOTIFICATION_LENGTH) {
2805 DPRINTF("short notification (%d<%d)\n",
2806 total_len, UCDC_NOTIFICATION_LENGTH);
2807 return;
2808 }
2809
2810 pc = usbd_xfer_get_frame(xfer, 0);
2811 usbd_copy_out(pc, 0, ¬ification, sizeof (notification));
2812
2813 if (notification.bmRequestType != UCDC_NOTIFICATION) {
2814 DPRINTF("unexpected notification (type=0x%02x)\n",
2815 notification.bmRequestType);
2816 return;
2817 }
2818
2819 switch (notification.bNotification) {
2820 case UCDC_N_NETWORK_CONNECTION:
2821 if (if_getflags(ifp) & IFF_DEBUG)
2822 log(LOG_DEBUG, "%s: network %sconnected\n",
2823 DEVNAM(sc),
2824 UGETW(notification.wValue)
2825 ? "" : "dis");
2826 break;
2827 case UCDC_N_RESPONSE_AVAILABLE:
2828 DPRINTFN(2, "umb_intr: response available\n");
2829 ++sc->sc_nresp;
2830 umb_add_task(sc, umb_get_response_task,
2831 &sc->sc_proc_get_response_task[0].hdr,
2832 &sc->sc_proc_get_response_task[1].hdr,
2833 0);
2834 break;
2835 case UCDC_N_CONNECTION_SPEED_CHANGE:
2836 DPRINTFN(2, "umb_intr: connection speed changed\n");
2837 break;
2838 default:
2839 DPRINTF("unexpected notification (0x%02x)\n",
2840 notification.bNotification);
2841 break;
2842 }
2843 /* fallthrough */
2844 case USB_ST_SETUP:
2845 tr_setup:
2846 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
2847 usbd_transfer_submit(xfer);
2848 break;
2849 default:
2850 if (status != USB_ERR_CANCELLED) {
2851 /* start clear stall */
2852 usbd_xfer_set_stall(xfer);
2853 goto tr_setup;
2854 }
2855 break;
2856 }
2857 }
2858
2859 /*
2860 * Diagnostic routines
2861 */
2862 static char *
umb_ntop(struct sockaddr * sa)2863 umb_ntop(struct sockaddr *sa)
2864 {
2865 #define NUMBUFS 4
2866 static char astr[NUMBUFS][INET_ADDRSTRLEN];
2867 static unsigned nbuf = 0;
2868 char *s;
2869
2870 s = astr[nbuf++];
2871 if (nbuf >= NUMBUFS)
2872 nbuf = 0;
2873
2874 switch (sa->sa_family) {
2875 case AF_INET:
2876 default:
2877 inet_ntop(AF_INET, &satosin(sa)->sin_addr, s, sizeof (astr[0]));
2878 break;
2879 case AF_INET6:
2880 inet_ntop(AF_INET6, &satosin6(sa)->sin6_addr, s,
2881 sizeof (astr[0]));
2882 break;
2883 }
2884 return s;
2885 }
2886
2887 #ifdef UMB_DEBUG
2888 static char *
umb_uuid2str(uint8_t uuid[MBIM_UUID_LEN])2889 umb_uuid2str(uint8_t uuid[MBIM_UUID_LEN])
2890 {
2891 static char uuidstr[2 * MBIM_UUID_LEN + 5];
2892
2893 #define UUID_BFMT "%02X"
2894 #define UUID_SEP "-"
2895 snprintf(uuidstr, sizeof (uuidstr),
2896 UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_SEP
2897 UUID_BFMT UUID_BFMT UUID_SEP
2898 UUID_BFMT UUID_BFMT UUID_SEP
2899 UUID_BFMT UUID_BFMT UUID_SEP
2900 UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT,
2901 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
2902 uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
2903 uuid[12], uuid[13], uuid[14], uuid[15]);
2904 return uuidstr;
2905 }
2906
2907 static void
umb_dump(void * buf,int len)2908 umb_dump(void *buf, int len)
2909 {
2910 int i = 0;
2911 uint8_t *c = buf;
2912
2913 if (len == 0)
2914 return;
2915 while (i < len) {
2916 if ((i % 16) == 0) {
2917 if (i > 0)
2918 log(LOG_DEBUG, "\n");
2919 log(LOG_DEBUG, "%4d: ", i);
2920 }
2921 log(LOG_DEBUG, " %02x", *c);
2922 c++;
2923 i++;
2924 }
2925 log(LOG_DEBUG, "\n");
2926 }
2927 #endif /* UMB_DEBUG */
2928
2929 DRIVER_MODULE(umb, uhub, umb_driver, NULL, NULL);
2930 MODULE_DEPEND(umb, usb, 1, 1, 1);
2931