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