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