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