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