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