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