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