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