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