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