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