Bug Summary

File:dev/usb/if_umb.c
Warning:line 997, column 14
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

Annotated Source Code

Press '?' to see keyboard shortcuts

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