View | Details | Raw Unified | Return to bug 263783 | Differences between
and this patch

Collapse All | Expand All

(-)b/lib/libifconfig/libifconfig_media.c (+5 lines)
Lines 78-83 static const struct ifmedia_description Link Here
78
    ifm_subtype_ethernet_option_descriptions[] =
78
    ifm_subtype_ethernet_option_descriptions[] =
79
    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
79
    IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
80
80
81
static const struct ifmedia_description
82
    ifm_subtype_mbim_descriptions[] =
83
    IFM_SUBTYPE_MBIM_DESCRIPTIONS;
84
81
static const struct ifmedia_description
85
static const struct ifmedia_description
82
    ifm_subtype_ieee80211_descriptions[] =
86
    ifm_subtype_ieee80211_descriptions[] =
83
    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
87
    IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
Lines 492-497 ifconfig_media_get_status(const struct ifmediareq *ifmr) Link Here
492
	switch (IFM_TYPE(ifmr->ifm_active)) {
496
	switch (IFM_TYPE(ifmr->ifm_active)) {
493
	case IFM_ETHER:
497
	case IFM_ETHER:
494
	case IFM_ATM:
498
	case IFM_ATM:
499
	case IFM_MBIM:
495
		if (ifmr->ifm_status & IFM_ACTIVE) {
500
		if (ifmr->ifm_status & IFM_ACTIVE) {
496
			return ("active");
501
			return ("active");
497
		} else {
502
		} else {
(-)b/sbin/Makefile (+1 lines)
Lines 63-68 SUBDIR=adjkerntz \ Link Here
63
	swapon \
63
	swapon \
64
	sysctl \
64
	sysctl \
65
	tunefs \
65
	tunefs \
66
	umbctl \
66
	umount
67
	umount
67
68
68
.if ${MK_INET} != "no" || ${MK_INET6} != "no"
69
.if ${MK_INET} != "no" || ${MK_INET6} != "no"
(-)b/sbin/umbctl/Makefile (+8 lines)
Added Link Here
1
CFLAGS+= -I${SRCTOP}/sys/dev/usb/net
2
3
PROG=	umbctl
4
MAN=	umbctl.8
5
6
BINDIR=	/sbin
7
8
.include <bsd.prog.mk>
(-)b/sbin/umbctl/umbctl.8 (+172 lines)
Added Link Here
1
.\"	$NetBSD$
2
.\"
3
.\" Copyright (c) 2018 by Pierre Pronchery <khorben@defora.org>
4
.\" All rights reserved.
5
.\"
6
.\" Redistribution and use in source and binary forms, with or without
7
.\" modification, are permitted provided that the following conditions
8
.\" are met:
9
.\" 1. Redistributions of source code must retain the above copyright
10
.\"    notice, this list of conditions and the following disclaimer.
11
.\" 2. Redistributions in binary form must reproduce the above copyright
12
.\"    notice, this list of conditions and the following disclaimer in the
13
.\"    documentation and/or other materials provided with the distribution.
14
.\"
15
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
.\" DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
.\" POSSIBILITY OF SUCH DAMAGE.
26
.\"
27
.\" From: pppoectl.8,v 1.30 2016/09/12 05:35:20 sevan Exp $
28
.\"
29
.\" $Id$
30
.\"
31
.\" last edit-date: [Thu Aug 31 10:47:33 2000]
32
.\"
33
.Dd March 22, 2020
34
.Dt UMBCTL 8
35
.Os
36
.Sh NAME
37
.Nm umbctl
38
.Nd display or set MBIM cellular modem interface parameters (4G/LTE)
39
.Sh SYNOPSIS
40
.Nm umbctl
41
.Op Fl v
42
.Ar ifname
43
.Op Ar parameter Op Ar value
44
.Ar ...
45
.Pp
46
.Nm umbctl
47
.Op Fl v
48
.Fl f Ar config-file
49
.Ar ifname
50
.Pp
51
.Nm umbctl
52
.Op Fl v
53
.Fl m Ar format
54
.Ar ifname
55
.Pp
56
.Sh DESCRIPTION
57
.Nm
58
supports the following options:
59
.Bl -tag -width XfXconfigXfileXXX -offset indent
60
.It Fl f Ar config-file
61
Parse
62
.Ar config-file
63
for
64
.Ar parameter Ns Op \&= Ns Ar value
65
pairs, one per line, as if they had been specified on the command line.
66
This allows the password or PIN codes to be not passed as command line
67
arguments.
68
Comments starting with # to the end of the current line are ignored.
69
.It Fl m Ar format
70
Displays the current settings in the
71
.Ar format
72
specified.
73
.It Fl v
74
Enables verbose mode.
75
.El
76
.Pp
77
The
78
.Xr umb 4
79
driver may require a number of additional arguments or optional
80
parameters besides the settings that can be adjusted with
81
.Xr ifconfig 8 .
82
These may be credentials or other tunable connectivity variables.
83
The
84
.Nm
85
utility can be used to display the current settings, or adjust these
86
parameters as required.
87
.Pp
88
For whatever intent
89
.Nm
90
is being called, at least the parameter
91
.Ar ifname
92
needs to be specified, naming the interface for which the settings
93
are to be performed or displayed.
94
Use
95
.Xr ifconfig 8
96
or
97
.Xr netstat 1
98
to see which interfaces are available.
99
.Pp
100
If no other parameter is given,
101
.Nm
102
will just list the current status for
103
.Ar ifname
104
and exit.
105
.Pp
106
If any additional parameter is supplied, superuser privileges are
107
required, and the command works in
108
.Ql set
109
mode.
110
This is normally done quietly, unless the option
111
.Fl v
112
is also enabled, which will cause a final printout of the status as
113
described above once all other actions have been taken.
114
.Pp
115
The parameters currently supported include:
116
.Bl -tag -width xxxxxxxxxxxxxxxxxxxxxxxxx -offset indent
117
.It Ar apn Ns \&= Ns Em access-point
118
Set the APN to
119
.Em access-point .
120
.It Ar username Ns \&= Ns Em username
121
Set the username to
122
.Em username .
123
.It Ar password Ns \&= Ns Em password
124
Set the password to
125
.Em password .
126
.It Ar pin Ns \&= Ns Em pin-code
127
Enter the PIN
128
.Em pin-code .
129
.It Ar puk Ns \&= Ns Em puk-code
130
Enter the PUK
131
.Em puk-code .
132
.It Ar roaming
133
Allow data connections when roaming.
134
.It Ar -roaming
135
Deny data connections when roaming.
136
.El
137
.Sh EXAMPLES
138
.Bd -literal
139
# umbctl umb0
140
umb0: state up, mode automatic, registration home network
141
	provider "BSD-Net", dataclass LTE, signal good
142
	phone number "+15554242", roaming "" (denied)
143
	APN "", TX 50000000, RX 100000000
144
	firmware "MBIM_FW_V1.0", hardware "MBIM_HW_V1.0"
145
.Ed
146
.Pp
147
Display the settings for umb0.
148
.Bd -literal
149
# umbctl umb0 apn operator.internet username mobile password mobile
150
.Ed
151
.Pp
152
Configure the connection parameters for umb0 from the command line.
153
.Bd -literal
154
# umbctl -f /dev/stdin umb0 << EOF
155
pin=1234
156
EOF
157
.Ed
158
.Pp
159
Configure the connection parameters for umb0 from a file.
160
.Sh SEE ALSO
161
.Xr netstat 1 ,
162
.Xr umb 4 ,
163
.Xr ifconfig 8 ,
164
.Xr ifwatchd 8
165
.Sh HISTORY
166
The
167
.Nm
168
utility first appeared in
169
.Nx 9.0 .
170
.Sh AUTHORS
171
The program was written by
172
.An Pierre Pronchery .
(-)b/sbin/umbctl/umbctl.c (+767 lines)
Added Link Here
1
/* $FreeBSD$ */
2
/* $NetBSD$ */
3
/*
4
 * Original copyright (c) 2018 Pierre Pronchery <khorben@defora.org> (for the
5
 * NetBSD Project)
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
17
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 *
27
 * Copyright (c) 2022 ADISTA SAS (FreeBSD updates)
28
 *
29
 * Updates for FreeBSD by Pierre Pronchery <pierre@defora.net>
30
 *
31
 * Redistribution and use in source and binary forms, with or without
32
 * modification, are permitted provided that the following conditions are met:
33
 *
34
 * - Redistributions of source code must retain the above copyright notice,
35
 *   this list of conditions and the following disclaimer.
36
 * - Redistributions in binary form must reproduce the above copyright notice,
37
 *   this list of conditions and the following disclaimer in the documentation
38
 *   and/or other materials provided with the distribution.
39
 * - Neither the name of the copyright holder nor the names of its contributors
40
 *   may be used to endorse or promote products derived from this software
41
 *   without specific prior written permission.
42
 *
43
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
44
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
47
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
53
 * POSSIBILITY OF SUCH DAMAGE.
54
 */
55
56
57
58
#include <sys/endian.h>
59
#include <sys/ioctl.h>
60
#include <sys/socket.h>
61
#include <sys/sockio.h>
62
63
#include <net/if.h>
64
#include <netinet/in.h>
65
#include <arpa/inet.h>
66
67
#include <ctype.h>
68
#include <errno.h>
69
#include <inttypes.h>
70
#include <stdarg.h>
71
#include <stdio.h>
72
#include <string.h>
73
#include <strings.h>
74
#include <unistd.h>
75
76
#include "mbim.h"
77
#include "if_umbreg.h"
78
79
80
/* constants */
81
static const struct umb_valdescr _umb_actstate[] =
82
	MBIM_ACTIVATION_STATE_DESCRIPTIONS;
83
84
static const struct umb_valdescr _umb_simstate[] =
85
	MBIM_SIMSTATE_DESCRIPTIONS;
86
87
static const struct umb_valdescr _umb_regstate[] =
88
	MBIM_REGSTATE_DESCRIPTIONS;
89
90
static const struct umb_valdescr _umb_pktstate[] =
91
	MBIM_PKTSRV_STATE_DESCRIPTIONS;
92
93
static const struct umb_valdescr _umb_dataclass[] =
94
	MBIM_DATACLASS_DESCRIPTIONS;
95
96
static const struct umb_valdescr _umb_state[] =
97
	UMB_INTERNAL_STATE_DESCRIPTIONS;
98
99
static const struct umb_valdescr _umb_pin_state[] =
100
{
101
	{ UMB_PIN_REQUIRED, "PIN required"},
102
	{ UMB_PIN_UNLOCKED, "PIN unlocked"},
103
	{ UMB_PUK_REQUIRED, "PUK required"},
104
	{ 0, NULL }
105
};
106
107
static const struct umb_valdescr _umb_regmode[] =
108
{
109
	{ MBIM_REGMODE_UNKNOWN, "unknown" },
110
	{ MBIM_REGMODE_AUTOMATIC, "automatic" },
111
	{ MBIM_REGMODE_MANUAL, "manual" },
112
	{ 0, NULL }
113
};
114
115
static const struct umb_valdescr _umb_ber[] =
116
{
117
	{ UMB_BER_EXCELLENT, "excellent" },
118
	{ UMB_BER_VERYGOOD, "very good" },
119
	{ UMB_BER_GOOD, "good" },
120
	{ UMB_BER_OK, "ok" },
121
	{ UMB_BER_MEDIUM, "medium" },
122
	{ UMB_BER_BAD, "bad" },
123
	{ UMB_BER_VERYBAD, "very bad" },
124
	{ UMB_BER_EXTREMELYBAD, "extremely bad" },
125
	{ 0, NULL }
126
};
127
128
129
/* prototypes */
130
static int _char_to_utf16(const char * in, uint16_t * out, size_t outlen);
131
static int _error(int ret, char const * format, ...);
132
static int _umbctl(char const * ifname, int verbose, int argc, char * argv[]);
133
static int _umbctl_file(char const * ifname, char const * filename,
134
		int verbose);
135
static int _umbctl_dump(char const * ifname, const char * format, int verbose);
136
static void _umbctl_dump_json(char const * ifname, struct umb_info * umbi);
137
static int _umbctl_gateway(char const * ifname);
138
static void _umbctl_info(char const * ifname, struct umb_info * umbi);
139
static int _umbctl_ioctl(char const * ifname, int fd, unsigned long request,
140
		struct ifreq * ifr);
141
static int _umbctl_set(char const * ifname, struct umb_parameter * umbp,
142
		int argc, char * argv[]);
143
static int _umbctl_socket(void);
144
static int _usage(void);
145
static void _print_utf16(uint16_t * in, int inlen);
146
static void _utf16_to_char(uint16_t * in, int inlen, char * out, size_t outlen);
147
148
149
/* functions */
150
/* char_to_utf16 */
151
/* this function is from OpenBSD's ifconfig(8) */
152
static int _char_to_utf16(const char * in, uint16_t * out, size_t outlen)
153
{
154
	int	n = 0;
155
	uint16_t c;
156
157
	for (;;) {
158
		c = *in++;
159
160
		if (c == '\0') {
161
			/*
162
			 * NUL termination is not required, but zero out the
163
			 * residual buffer
164
			 */
165
			memset(out, 0, outlen);
166
			return n;
167
		}
168
		if (outlen < sizeof(*out))
169
			return -1;
170
171
		*out++ = htole16(c);
172
		n += sizeof(*out);
173
		outlen -= sizeof(*out);
174
	}
175
}
176
177
178
/* error */
179
static int _error(int ret, char const * format, ...)
180
{
181
	va_list ap;
182
183
	fputs("umbctl: ", stderr);
184
	va_start(ap, format);
185
	vfprintf(stderr, format, ap);
186
	va_end(ap);
187
	fputs("\n", stderr);
188
	return ret;
189
}
190
191
192
/* umbctl */
193
static int _umbctl(char const * ifname, int verbose, int argc, char * argv[])
194
{
195
	int fd;
196
	struct ifreq ifr;
197
	struct umb_info umbi;
198
	struct umb_parameter umbp;
199
200
	if((fd = _umbctl_socket()) < 0)
201
		return 2;
202
	memset(&ifr, 0, sizeof(ifr));
203
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
204
	if(argc != 0)
205
	{
206
		memset(&umbp, 0, sizeof(umbp));
207
		ifr.ifr_data = (caddr_t)&umbp;
208
		if(_umbctl_ioctl(ifname, fd, SIOCGUMBPARAM, &ifr) != 0
209
				|| _umbctl_set(ifname, &umbp, argc, argv) != 0
210
				|| _umbctl_ioctl(ifname, fd, SIOCSUMBPARAM,
211
					&ifr) != 0)
212
		{
213
			close(fd);
214
			return 2;
215
		}
216
	}
217
	if(argc == 0 || verbose > 0)
218
	{
219
		ifr.ifr_data = (caddr_t)&umbi;
220
		if(_umbctl_ioctl(ifname, fd, SIOCGUMBINFO, &ifr) != 0)
221
		{
222
			close(fd);
223
			return 3;
224
		}
225
		_umbctl_info(ifname, &umbi);
226
	}
227
	if(close(fd) != 0)
228
		return _error(2, "%s: %s", ifname, strerror(errno));
229
	return 0;
230
}
231
232
233
/* umbctl_file */
234
static int _file_parse(char const * ifname, struct umb_parameter * umbp,
235
		char const * filename);
236
237
static int _umbctl_file(char const * ifname, char const * filename, int verbose)
238
{
239
	int fd;
240
	struct ifreq ifr;
241
	struct umb_parameter umbp;
242
	struct umb_info umbi;
243
244
	if((fd = _umbctl_socket()) < 0)
245
		return 2;
246
	memset(&ifr, 0, sizeof(ifr));
247
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
248
	ifr.ifr_data = (caddr_t)&umbp;
249
	memset(&umbp, 0, sizeof(umbp));
250
	if(_umbctl_ioctl(ifname, fd, SIOCGUMBPARAM, &ifr) != 0
251
			|| _file_parse(ifname, &umbp, filename) != 0
252
			|| _umbctl_ioctl(ifname, fd, SIOCSUMBPARAM, &ifr) != 0)
253
	{
254
		close(fd);
255
		return 2;
256
	}
257
	if(verbose > 0)
258
	{
259
		ifr.ifr_data = (caddr_t)&umbi;
260
		if(_umbctl_ioctl(ifname, fd, SIOCGUMBINFO, &ifr) != 0)
261
		{
262
			close(fd);
263
			return 3;
264
		}
265
		_umbctl_info(ifname, &umbi);
266
	}
267
	if(close(fd) != 0)
268
		return _error(2, "%s: %s", ifname, strerror(errno));
269
	return 0;
270
}
271
272
static int _file_parse(char const * ifname, struct umb_parameter * umbp,
273
		char const * filename)
274
{
275
	int ret = 0;
276
	FILE * fp;
277
	char buf[512];
278
	size_t len;
279
	int i;
280
	int eof;
281
	char * tokens[3] = { buf, NULL, NULL };
282
	char * p;
283
284
	if((fp = fopen(filename, "r")) == NULL)
285
		return _error(2, "%s: %s", filename, strerror(errno));
286
	while(fgets(buf, sizeof(buf), fp) != NULL)
287
	{
288
		if(buf[0] == '#')
289
			continue;
290
		buf[sizeof(buf) - 1] = '\0';
291
		if((len = strlen(buf)) > 0)
292
		{
293
			if(buf[len - 1] != '\n')
294
			{
295
				ret = _error(2, "%s: %s", filename,
296
						"Line too long");
297
				while((i = fgetc(fp)) != EOF && i != '\n');
298
				continue;
299
			}
300
			buf[len - 1] = '\0';
301
		}
302
		if((p = strchr(buf, '=')) != NULL)
303
		{
304
			tokens[1] = p + 1;
305
			*p = '\0';
306
		} else
307
			tokens[1] = NULL;
308
		ret |= _umbctl_set(ifname, umbp, (p != NULL) ? 2 : 1, tokens)
309
			? 2 : 0;
310
	}
311
	eof = feof(fp);
312
	if(fclose(fp) != 0 || !eof)
313
		return _error(2, "%s: %s", filename, strerror(errno));
314
	return ret;
315
}
316
317
318
/* umbctl_dump */
319
static int _umbctl_dump(char const * ifname, const char * format, int verbose)
320
{
321
	int fd;
322
	struct ifreq ifr;
323
	struct umb_info umbi;
324
	(void) verbose;
325
326
	if((fd = _umbctl_socket()) < 0)
327
		return 2;
328
	memset(&ifr, 0, sizeof(ifr));
329
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
330
	ifr.ifr_data = (caddr_t)&umbi;
331
	if(_umbctl_ioctl(ifname, fd, SIOCGUMBINFO, &ifr) != 0)
332
	{
333
		close(fd);
334
		return 3;
335
	}
336
	if(close(fd) != 0)
337
		return _error(2, "%s: %s", ifname, strerror(errno));
338
	if(strncasecmp(format, "JSON", 4) == 0)
339
		_umbctl_dump_json(ifname, &umbi);
340
	else
341
		return _error(2, "%s: Unsupported format", format);
342
	return 0;
343
}
344
345
346
/* umbctl_dump_json */
347
static void _umbctl_dump_json(char const * ifname, struct umb_info * umbi)
348
{
349
#define JSON_START	printf("{")
350
#define JSON_END	printf("}\n")
351
#define JSON_SEP	printf(", ")
352
#define JSON_ARRAY_START	printf("[")
353
#define JSON_ARRAY_END	printf("]")
354
355
#define JSON_STRING(key, val)	printf("\"%s\": \"%s\"", key, val)
356
#define JSON_INT(key, val)	printf("\"%s\": %d", key, val)
357
#define JSON_ULONG(key, val)	printf("\"%s\": %lu", key, val)
358
#define JSON_BOOL(key, val)	printf("\"%s\": %s", key, (val)?"true":"false")
359
#define JSON_NULL(key)		printf("\"%s\": null", key)
360
#define JSON_KEY(key)		printf("\"%s\": ", key)
361
362
#define JSON_WSTRING(key, val, len)	(printf("\"%s\": \"", key),\
363
					 _print_utf16(val, len),printf("\""))
364
365
#define JSON_NULL_EMPTY(key, val)	(*val != '\0')?JSON_STRING(key, val):\
366
					JSON_NULL(key)
367
#define JSON_NULL_WEMPTY(key, val, len)	((char)htole16(*val) != '\0')?\
368
					JSON_WSTRING(key, val, len):\
369
					JSON_NULL(key)
370
371
	JSON_START;
372
	JSON_STRING("interface", ifname);
373
	JSON_SEP;
374
	JSON_NULL_EMPTY("state", umb_val2descr(_umb_state, umbi->state));
375
	JSON_SEP;
376
	JSON_NULL_EMPTY("pin-status", umb_val2descr(_umb_pin_state, umbi->pin_state));
377
	JSON_SEP;
378
	JSON_INT("pin-attempts-left", umbi->pin_attempts_left);
379
	JSON_SEP;
380
	JSON_NULL_EMPTY("activation", umb_val2descr(_umb_actstate, umbi->activation));
381
	JSON_SEP;
382
	JSON_NULL_EMPTY("sim-state", umb_val2descr(_umb_simstate, umbi->sim_state));
383
	JSON_SEP;
384
	JSON_NULL_EMPTY("sim-registration", umb_val2descr(_umb_regstate, umbi->regstate));
385
	JSON_SEP;
386
	JSON_NULL_EMPTY("sim-registration-mode", umb_val2descr(_umb_regmode, umbi->regmode));
387
	JSON_SEP;
388
	JSON_INT("network-errors", umbi->nwerror);
389
	JSON_SEP;
390
	JSON_NULL_EMPTY("packet-state", umb_val2descr(_umb_pktstate, umbi->packetstate));
391
	JSON_SEP;
392
	JSON_NULL_EMPTY("supported-dataclasses", umb_val2descr(_umb_dataclass, umbi->supportedclasses));
393
	JSON_SEP;
394
	JSON_NULL_EMPTY("preferred-dataclasses", umb_val2descr(_umb_dataclass, umbi->preferredclasses));
395
	JSON_SEP;
396
	JSON_NULL_EMPTY("offered-dataclasses", umb_val2descr(_umb_dataclass, umbi->highestclass));
397
	JSON_SEP;
398
	JSON_NULL_EMPTY("dataclass", umb_val2descr(_umb_dataclass, umbi->cellclass));
399
	JSON_SEP;
400
	JSON_NULL_WEMPTY("provider", umbi->provider, UMB_PROVIDERNAME_MAXLEN);
401
	JSON_SEP;
402
	JSON_NULL_WEMPTY("phone-number", umbi->pn, UMB_PHONENR_MAXLEN);
403
	JSON_SEP;
404
	JSON_NULL_WEMPTY("subscriber-id", umbi->sid, UMB_SUBSCRIBERID_MAXLEN);
405
	JSON_SEP;
406
	JSON_NULL_WEMPTY("iccid", umbi->iccid, UMB_ICCID_MAXLEN);
407
	JSON_SEP;
408
	JSON_BOOL("roaming-on", umbi->enable_roaming);
409
	JSON_SEP;
410
	JSON_NULL_WEMPTY("roaming-text", umbi->roamingtxt, UMB_ROAMINGTEXT_MAXLEN);
411
	JSON_SEP;
412
	JSON_NULL_WEMPTY("device-id", umbi->devid, UMB_DEVID_MAXLEN);
413
	JSON_SEP;
414
	JSON_NULL_WEMPTY("firmware", umbi->fwinfo, UMB_FWINFO_MAXLEN);
415
	JSON_SEP;
416
	JSON_NULL_WEMPTY("hardware", umbi->hwinfo, UMB_HWINFO_MAXLEN);
417
	JSON_SEP;
418
	JSON_NULL_WEMPTY("access-point-name", umbi->apn, UMB_APN_MAXLEN);
419
	JSON_SEP;
420
	JSON_NULL_WEMPTY("username", umbi->username, UMB_USERNAME_MAXLEN);
421
	JSON_SEP;
422
	JSON_NULL_WEMPTY("password", umbi->password, UMB_PASSWORD_MAXLEN);
423
	JSON_SEP;
424
	JSON_INT("rssi", umbi->rssi);
425
	JSON_SEP;
426
	JSON_INT("bit-error-rate", umbi->ber);
427
	JSON_SEP;
428
	JSON_BOOL("hw-radio-on", umbi->hw_radio_on);
429
	JSON_SEP;
430
	JSON_BOOL("sw-radio-on", umbi->sw_radio_on);
431
	JSON_SEP;
432
	JSON_ULONG("uplink-speed", umbi->uplink_speed);
433
	JSON_SEP;
434
	JSON_ULONG("downlink-speed", umbi->downlink_speed);
435
	JSON_SEP;
436
	JSON_KEY("ipv4-dns");
437
	JSON_ARRAY_START;
438
	/* TODO: Implement the DNS servers in the JSON object
439
	#define UMB_MAX_DNSSRV			2
440
		u_int32_t		ipv4dns[UMB_MAX_DNSSRV];
441
442
		XXX: The ipv4dns is either of maximum size or null terminated
443
		     (it's memset to 0)
444
	*/
445
	JSON_ARRAY_END;
446
	JSON_END;
447
}
448
449
450
/* umbctl_gateway */
451
static int _umbctl_gateway(char const * ifname)
452
{
453
	int fd;
454
	struct ifreq ifr;
455
	struct sockaddr_in * sin;
456
457
	if((fd = _umbctl_socket()) < 0)
458
		return 2;
459
	memset(&ifr, 0, sizeof(ifr));
460
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
461
	if(_umbctl_ioctl(ifname, fd, SIOCGIFDSTADDR, &ifr) != 0)
462
	{
463
		close(fd);
464
		return 2;
465
	}
466
	sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
467
	printf("%s\n", inet_ntoa(sin->sin_addr));
468
	if(close(fd) != 0)
469
		return _error(2, "%s: %s", ifname, strerror(errno));
470
	return 0;
471
}
472
473
474
/* umbctl_info */
475
static void _umbctl_info(char const * ifname, struct umb_info * umbi)
476
{
477
	char provider[UMB_PROVIDERNAME_MAXLEN + 1];
478
	char pn[UMB_PHONENR_MAXLEN + 1];
479
	char roaming[UMB_ROAMINGTEXT_MAXLEN + 1];
480
	char apn[UMB_APN_MAXLEN + 1];
481
	char fwinfo[UMB_FWINFO_MAXLEN + 1];
482
	char hwinfo[UMB_HWINFO_MAXLEN + 1];
483
484
	_utf16_to_char(umbi->provider, UMB_PROVIDERNAME_MAXLEN,
485
			provider, sizeof(provider));
486
	_utf16_to_char(umbi->pn, UMB_PHONENR_MAXLEN, pn, sizeof(pn));
487
	_utf16_to_char(umbi->roamingtxt, UMB_ROAMINGTEXT_MAXLEN,
488
			roaming, sizeof(roaming));
489
	_utf16_to_char(umbi->apn, UMB_APN_MAXLEN, apn, sizeof(apn));
490
	_utf16_to_char(umbi->fwinfo, UMB_FWINFO_MAXLEN, fwinfo, sizeof(fwinfo));
491
	_utf16_to_char(umbi->hwinfo, UMB_HWINFO_MAXLEN, hwinfo, sizeof(hwinfo));
492
	printf("%s: state %s, mode %s, registration %s\n"
493
			"\tprovider \"%s\", dataclass %s, signal %s\n"
494
			"\tphone number \"%s\", roaming \"%s\" (%s)\n"
495
			"\tAPN \"%s\", TX %" PRIu64 ", RX %" PRIu64 "\n"
496
			"\tfirmware \"%s\", hardware \"%s\"\n",
497
			ifname, umb_val2descr(_umb_state, umbi->state),
498
			umb_val2descr(_umb_regmode, umbi->regmode),
499
			umb_val2descr(_umb_regstate, umbi->regstate), provider,
500
			umb_val2descr(_umb_dataclass, umbi->cellclass),
501
			umb_val2descr(_umb_ber, umbi->ber), pn, roaming,
502
			umbi->enable_roaming ? "allowed" : "denied",
503
			apn, umbi->uplink_speed, umbi->downlink_speed,
504
			fwinfo, hwinfo);
505
}
506
507
/* print_utf16 */
508
static void _print_utf16(uint16_t * in, int inlen)
509
{
510
	/* XXX Note to readers:
511
	 *
512
	 * The function was originally:
513
	 * do
514
	 * 	putc(isascii((char)htole16(*in)) ? (char)htole16(*in) : '?', stdout);
515
	 * while ((char)htole16(*(in++)) != '\0' && --inlen > 0);
516
	 *
517
	 * but in an effort to reuse the code, it is better to call
518
	 * _utf16_to_char instead.
519
	 */
520
	char buf[inlen + 1];
521
522
	_utf16_to_char(in, inlen, buf, inlen);
523
	buf[inlen] = '\0';
524
	printf("%s", buf);
525
}
526
527
/* umbctl_ioctl */
528
static int _umbctl_ioctl(char const * ifname, int fd, unsigned long request,
529
		struct ifreq * ifr)
530
{
531
	if(ioctl(fd, request, ifr) != 0)
532
		return _error(-1, "%s: %s", ifname, strerror(errno));
533
	return 0;
534
}
535
536
537
/* umbctl_set */
538
/* callbacks */
539
static int _set_apn(char const *, struct umb_parameter *, char const *);
540
static int _set_username(char const *, struct umb_parameter *, char const *);
541
static int _set_password(char const *, struct umb_parameter *, char const *);
542
static int _set_pin(char const *, struct umb_parameter *, char const *);
543
static int _set_puk(char const *, struct umb_parameter *, char const *);
544
static int _set_roaming_allow(char const *, struct umb_parameter *,
545
		char const *);
546
static int _set_roaming_deny(char const *, struct umb_parameter *,
547
		char const *);
548
549
static int _umbctl_set(char const * ifname, struct umb_parameter * umbp,
550
		int argc, char * argv[])
551
{
552
	struct
553
	{
554
		char const * name;
555
		int (*callback)(char const *,
556
				struct umb_parameter *, char const *);
557
		int parameter;
558
	} callbacks[] =
559
	{
560
		{ "apn", _set_apn, 1 },
561
		{ "username", _set_username, 1 },
562
		{ "password", _set_password, 1 },
563
		{ "pin", _set_pin, 1 },
564
		{ "puk", _set_puk, 1 },
565
		{ "roaming", _set_roaming_allow, 0 },
566
		{ "-roaming", _set_roaming_deny, 0 },
567
	};
568
	int i;
569
	size_t j;
570
571
	for(i = 0; i < argc; i++)
572
	{
573
		for(j = 0; j < sizeof(callbacks) / sizeof(*callbacks); j++)
574
			if(strcmp(argv[i], callbacks[j].name) == 0)
575
			{
576
				if(callbacks[j].parameter && i + 1 == argc)
577
					return _error(-1, "%s: Incomplete"
578
							" parameter", argv[i]);
579
				if(callbacks[j].callback(ifname, umbp,
580
							callbacks[j].parameter
581
							? argv[i + 1] : NULL))
582
					return -1;
583
				if(callbacks[j].parameter)
584
					i++;
585
				break;
586
			}
587
		if(j == sizeof(callbacks) / sizeof(*callbacks))
588
			return _error(-1, "%s: Unknown parameter", argv[i]);
589
	}
590
	return 0;
591
}
592
593
static int _set_apn(char const * ifname, struct umb_parameter * umbp,
594
		char const * apn)
595
{
596
	umbp->apnlen = _char_to_utf16(apn, umbp->apn, sizeof(umbp->apn));
597
	if(umbp->apnlen < 0 || (size_t)umbp->apnlen > sizeof(umbp->apn))
598
		return _error(-1, "%s: %s", ifname, "APN too long");
599
	return 0;
600
}
601
602
static int _set_username(char const * ifname, struct umb_parameter * umbp,
603
		char const * username)
604
{
605
	umbp->usernamelen = _char_to_utf16(username, umbp->username,
606
			sizeof(umbp->username));
607
	if(umbp->usernamelen < 0
608
			|| (size_t)umbp->usernamelen > sizeof(umbp->username))
609
		return _error(-1, "%s: %s", ifname, "Username too long");
610
	return 0;
611
}
612
613
static int _set_password(char const * ifname, struct umb_parameter * umbp,
614
		char const * password)
615
{
616
	umbp->passwordlen = _char_to_utf16(password, umbp->password,
617
			sizeof(umbp->password));
618
	if(umbp->passwordlen < 0
619
			|| (size_t)umbp->passwordlen > sizeof(umbp->password))
620
		return _error(-1, "%s: %s", ifname, "Password too long");
621
	return 0;
622
}
623
624
static int _set_pin(char const * ifname, struct umb_parameter * umbp,
625
		char const * pin)
626
{
627
	umbp->is_puk = 0;
628
	umbp->op = MBIM_PIN_OP_ENTER;
629
	umbp->pinlen = _char_to_utf16(pin, umbp->pin, sizeof(umbp->pin));
630
	if(umbp->pinlen < 0 || (size_t)umbp->pinlen
631
			> sizeof(umbp->pin))
632
		return _error(-1, "%s: %s", ifname, "PIN code too long");
633
	return 0;
634
}
635
636
static int _set_puk(char const * ifname, struct umb_parameter * umbp,
637
		char const * puk)
638
{
639
	umbp->is_puk = 1;
640
	umbp->op = MBIM_PIN_OP_ENTER;
641
	umbp->pinlen = _char_to_utf16(puk, umbp->pin, sizeof(umbp->pin));
642
	if(umbp->pinlen < 0 || (size_t)umbp->pinlen > sizeof(umbp->pin))
643
		return _error(-1, "%s: %s", ifname, "PUK code too long");
644
	return 0;
645
}
646
647
static int _set_roaming_allow(char const * ifname, struct umb_parameter * umbp,
648
		char const * unused)
649
{
650
	(void) ifname;
651
	(void) unused;
652
653
	umbp->roaming = 1;
654
	return 0;
655
}
656
657
static int _set_roaming_deny(char const * ifname, struct umb_parameter * umbp,
658
		char const * unused)
659
{
660
	(void) ifname;
661
	(void) unused;
662
663
	umbp->roaming = 0;
664
	return 0;
665
}
666
667
668
/* umbctl_socket */
669
static int _umbctl_socket(void)
670
{
671
	int fd;
672
673
	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
674
		return _error(-1, "socket: %s", strerror(errno));
675
	return fd;
676
}
677
678
679
/* usage */
680
static int _usage(void)
681
{
682
	fputs("Usage: umbctl [-v] ifname [parameter [value]] [...]\n"
683
"       umbctl -f config-file ifname\n"
684
"       umbctl -g ifname\n"
685
"       umbctl -m format ifname [...]\n"
686
"\n"
687
"Note: -f and -m are mutually exclusive. The only supported format is JSON.\n",
688
			stderr);
689
	return 1;
690
}
691
692
693
/* utf16_to_char */
694
static void _utf16_to_char(uint16_t * in, int inlen, char * out, size_t outlen)
695
{
696
	uint16_t c;
697
698
	while (outlen > 0) {
699
		c = inlen > 0 ? htole16(*in) : 0;
700
		if (c == 0 || --outlen == 0) {
701
			/* always NUL terminate result */
702
			*out = '\0';
703
			break;
704
		}
705
		*out++ = isascii(c) ? (char)c : '?';
706
		in++;
707
		inlen--;
708
	}
709
}
710
711
712
/* main */
713
int main(int argc, char * argv[])
714
{
715
	int o;
716
	char const * filename = NULL;
717
	char const * format = NULL;
718
	int gateway = 0;
719
	int verbose = 0;
720
721
	while((o = getopt(argc, argv, "f:gm:v")) != -1)
722
		switch(o)
723
		{
724
			case 'f':
725
				filename = optarg;
726
				format = NULL;
727
				gateway = 0;
728
				break;
729
			case 'g':
730
				filename = NULL;
731
				format = NULL;
732
				gateway = 1;
733
				break;
734
			case 'm':
735
				filename = NULL;
736
				format = optarg;
737
				gateway = 0;
738
				break;
739
			case 'v':
740
				verbose++;
741
				break;
742
			default:
743
				return _usage();
744
		}
745
	if(optind == argc)
746
		return _usage();
747
	if(filename != NULL)
748
	{
749
		if(optind + 1 != argc)
750
			return _usage();
751
		return _umbctl_file(argv[optind], filename, verbose);
752
	}
753
	if(format != NULL)
754
	{
755
		if(optind + 1 != argc)
756
			return _usage();
757
		return _umbctl_dump(argv[optind], format, verbose);
758
	}
759
	if(gateway)
760
	{
761
		if(optind + 1 != argc)
762
			return _usage();
763
		return _umbctl_gateway(argv[optind]);
764
	}
765
	return _umbctl(argv[optind], verbose, argc - optind - 1,
766
			&argv[optind + 1]);
767
}
(-)b/share/man/man4/Makefile (+1 lines)
Lines 1045-1050 MAN+= \ Link Here
1045
	uled.4 \
1045
	uled.4 \
1046
	ulpt.4 \
1046
	ulpt.4 \
1047
	umass.4 \
1047
	umass.4 \
1048
	umb.4 \
1048
	umcs.4 \
1049
	umcs.4 \
1049
	umct.4 \
1050
	umct.4 \
1050
	umodem.4 \
1051
	umodem.4 \
(-)b/share/man/man4/umb.4 (+90 lines)
Added Link Here
1
.\" $NetBSD: umb.4,v 1.4 2019/08/30 09:22:17 wiz Exp $
2
.\"
3
.\" Copyright (c) 2016 genua mbH
4
.\"
5
.\" Permission to use, copy, modify, and distribute this software for any
6
.\" purpose with or without fee is hereby granted, provided that the above
7
.\" copyright notice and this permission notice appear in all copies.
8
.\"
9
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
.\"
17
.Dd August 24, 2019
18
.Dt UMB 4
19
.Os
20
.Sh NAME
21
.Nm umb
22
.Nd USB Mobile Broadband Interface Model (MBIM)
23
.Sh SYNOPSIS
24
.Cd "umb*  at uhub? port?"
25
.Sh DESCRIPTION
26
The
27
.Nm
28
driver provides support for USB MBIM devices.
29
.Pp
30
MBIM devices establish connections via cellular networks such as
31
GPRS, UMTS, and LTE.
32
They appear as a regular point-to-point network interface,
33
transporting raw IP frames.
34
.Pp
35
Required configuration parameters like PIN and APN have to be set
36
with
37
.Xr umbctl 8 .
38
Once the SIM card has been unlocked with the correct PIN, it
39
will remain in this state until the MBIM device is power-cycled.
40
In case the device is connected to an "always-on" USB port,
41
it may be possible to connect to a provider without entering the
42
PIN again even if the system was rebooted.
43
.Sh HARDWARE
44
The following devices should work:
45
.Pp
46
.Bl -tag -width Ds -offset indent -compact
47
.It Ericsson H5321gw and N5321gw
48
.It Fibocom L831-EAU
49
.It Medion Mobile S4222 (MediaTek OEM)
50
.It Sierra Wireless EM7345
51
.It Sierra Wireless EM7455
52
.It Sierra Wireless EM8805
53
.It Sierra Wireless MC8305
54
.El
55
.Sh SEE ALSO
56
.Xr intro 4 ,
57
.Xr netintro 4 ,
58
.Xr usb 4 ,
59
.Xr ifconfig.if 5 ,
60
.Xr ifconfig 8 ,
61
.Xr umbctl 8
62
.Rs
63
.%T "Universal Serial Bus Communications Class Subclass Specification for Mobile Broadband Interface Model"
64
.%U http://www.usb.org/developers/docs/devclass_docs/MBIM10Errata1_073013.zip
65
.Re
66
.Sh HISTORY
67
The
68
.Nm
69
device driver first appeared in
70
.Ox 6.0
71
and
72
.Nx 9.0 .
73
.Sh AUTHORS
74
.An -nosplit
75
The
76
.Nm
77
driver was written by
78
.An Gerhard Roth Aq Mt gerhard@openbsd.org
79
and ported from
80
.Ox
81
by
82
.An Pierre Pronchery Aq Mt khorben@defora.org .
83
.Sh CAVEATS
84
The
85
.Nm
86
driver does not support IPv6.
87
.Pp
88
Devices which fail to provide a conforming MBIM implementation will
89
probably be attached as some other driver, such as
90
.Xr u3g 4 .
(-)b/sys/conf/files (+1 lines)
Lines 3307-3312 dev/usb/net/if_muge.c optional muge Link Here
3307
dev/usb/net/if_rue.c		optional rue
3307
dev/usb/net/if_rue.c		optional rue
3308
dev/usb/net/if_smsc.c		optional smsc
3308
dev/usb/net/if_smsc.c		optional smsc
3309
dev/usb/net/if_udav.c		optional udav
3309
dev/usb/net/if_udav.c		optional udav
3310
dev/usb/net/if_umb.c		optional umb
3310
dev/usb/net/if_ure.c		optional ure
3311
dev/usb/net/if_ure.c		optional ure
3311
dev/usb/net/if_usie.c		optional usie
3312
dev/usb/net/if_usie.c		optional usie
3312
dev/usb/net/if_urndis.c		optional urndis
3313
dev/usb/net/if_urndis.c		optional urndis
(-)b/sys/dev/usb/net/if_umb.c (+2931 lines)
Added Link Here
1
/*	$FreeBSD$ */
2
/*	$NetBSD$ */
3
/*	$OpenBSD: if_umb.c,v 1.18 2018/02/19 08:59:52 mpi Exp $ */
4
5
/*
6
 * Original copyright (c) 2016 genua mbH (OpenBSD version)
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 *
20
 * Copyright (c) 2022 ADISTA SAS (re-write for FreeBSD)
21
 *
22
 * Re-write for FreeBSD by Pierre Pronchery <pierre@defora.net>
23
 *
24
 * Redistribution and use in source and binary forms, with or without
25
 * modification, are permitted provided that the following conditions are met:
26
 *
27
 * - Redistributions of source code must retain the above copyright notice,
28
 *   this list of conditions and the following disclaimer.
29
 * - Redistributions in binary form must reproduce the above copyright notice,
30
 *   this list of conditions and the following disclaimer in the documentation
31
 *   and/or other materials provided with the distribution.
32
 * - Neither the name of the copyright holder nor the names of its contributors
33
 *   may be used to endorse or promote products derived from this software
34
 *   without specific prior written permission.
35
 *
36
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
37
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
40
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46
 * POSSIBILITY OF SUCH DAMAGE.
47
 */
48
49
/*
50
 * Mobile Broadband Interface Model specification:
51
 * http://www.usb.org/developers/docs/devclass_docs/MBIM10Errata1_073013.zip
52
 * Compliance testing guide
53
 * http://www.usb.org/developers/docs/devclass_docs/MBIM-Compliance-1.0.pdf
54
 */
55
56
#include <sys/param.h>
57
#include <sys/module.h>
58
#include <sys/endian.h>
59
#include <sys/kernel.h>
60
#include <sys/mbuf.h>
61
#include <sys/priv.h>
62
#include <sys/socket.h>
63
#include <sys/sockio.h>
64
#include <sys/systm.h>
65
#include <sys/syslog.h>
66
#include <sys/kernel.h>
67
#include <sys/queue.h>
68
69
#include <sys/conf.h>
70
#include <sys/bus.h>
71
#include <sys/mutex.h>
72
#include <sys/condvar.h>
73
#include <sys/taskqueue.h>
74
75
#include <machine/_inttypes.h>
76
77
#include <net/bpf.h>
78
#include <net/if.h>
79
#include <net/if_media.h>
80
#include <net/if_types.h>
81
#include <net/if_var.h>
82
#include <net/netisr.h>
83
#include <net/route.h>
84
85
#include <netinet/in.h>
86
#include <netinet/in_var.h>
87
#include <netinet/ip.h>
88
89
#include <dev/usb/usb.h>
90
#include <dev/usb/usb_cdc.h>
91
#include <dev/usb/usbdi.h>
92
#include <dev/usb/usb_device.h>
93
#include <dev/usb/usb_process.h>
94
#include <dev/usb/usbdi_util.h>
95
#include "usb_if.h"
96
97
#include "mbim.h"
98
#include "if_umbreg.h"
99
100
MALLOC_DECLARE(M_MBIM_CID_CONNECT);
101
MALLOC_DEFINE(M_MBIM_CID_CONNECT, "mbim_cid_connect",
102
		"Connection parameters for MBIM");
103
104
#ifdef UMB_DEBUG
105
#define DPRINTF(x...)							\
106
		do { if (umb_debug) log(LOG_DEBUG, x); } while (0)
107
108
#define DPRINTFN(n, x...)						\
109
		do { if (umb_debug >= (n)) log(LOG_DEBUG, x); } while (0)
110
111
#define DDUMPN(n, b, l)							\
112
		do {							\
113
			if (umb_debug >= (n))				\
114
				umb_dump((b), (l));			\
115
		} while (0)
116
117
const int	 umb_debug = 1;
118
static char	*umb_uuid2str(uint8_t [MBIM_UUID_LEN]);
119
static void	 umb_dump(void *, int);
120
121
#else
122
#define DPRINTF(x...)		do { } while (0)
123
#define DPRINTFN(n, x...)	do { } while (0)
124
#define DDUMPN(n, b, l)		do { } while (0)
125
#endif
126
127
#define DEVNAM(sc)		device_get_nameunit((sc)->sc_dev)
128
129
/*
130
 * State change timeout
131
 */
132
#define UMB_STATE_CHANGE_TIMEOUT	30
133
134
/*
135
 * State change flags
136
 */
137
#define UMB_NS_DONT_DROP	0x0001	/* do not drop below current state */
138
#define UMB_NS_DONT_RAISE	0x0002	/* do not raise below current state */
139
140
/*
141
 * Diagnostic macros
142
 */
143
const struct umb_valdescr umb_regstates[] = MBIM_REGSTATE_DESCRIPTIONS;
144
const struct umb_valdescr umb_dataclasses[] = MBIM_DATACLASS_DESCRIPTIONS;
145
const struct umb_valdescr umb_simstate[] = MBIM_SIMSTATE_DESCRIPTIONS;
146
const struct umb_valdescr umb_messages[] = MBIM_MESSAGES_DESCRIPTIONS;
147
const struct umb_valdescr umb_status[] = MBIM_STATUS_DESCRIPTIONS;
148
const struct umb_valdescr umb_cids[] = MBIM_CID_DESCRIPTIONS;
149
const struct umb_valdescr umb_pktstate[] = MBIM_PKTSRV_STATE_DESCRIPTIONS;
150
const struct umb_valdescr umb_actstate[] = MBIM_ACTIVATION_STATE_DESCRIPTIONS;
151
const struct umb_valdescr umb_error[] = MBIM_ERROR_DESCRIPTIONS;
152
const struct umb_valdescr umb_pintype[] = MBIM_PINTYPE_DESCRIPTIONS;
153
const struct umb_valdescr umb_istate[] = UMB_INTERNAL_STATE_DESCRIPTIONS;
154
155
#define umb_regstate(c)		umb_val2descr(umb_regstates, (c))
156
#define umb_dataclass(c)	umb_val2descr(umb_dataclasses, (c))
157
#define umb_simstate(s)		umb_val2descr(umb_simstate, (s))
158
#define umb_request2str(m)	umb_val2descr(umb_messages, (m))
159
#define umb_status2str(s)	umb_val2descr(umb_status, (s))
160
#define umb_cid2str(c)		umb_val2descr(umb_cids, (c))
161
#define umb_packet_state(s)	umb_val2descr(umb_pktstate, (s))
162
#define umb_activation(s)	umb_val2descr(umb_actstate, (s))
163
#define umb_error2str(e)	umb_val2descr(umb_error, (e))
164
#define umb_pin_type(t)		umb_val2descr(umb_pintype, (t))
165
#define umb_istate(s)		umb_val2descr(umb_istate, (s))
166
167
static device_probe_t umb_probe;
168
static device_attach_t umb_attach;
169
static device_detach_t umb_detach;
170
static device_suspend_t umb_suspend;
171
static device_resume_t umb_resume;
172
static void	 umb_attach_task(struct usb_proc_msg *);
173
static usb_handle_request_t umb_handle_request;
174
static int	 umb_deactivate(device_t);
175
static void	 umb_ncm_setup(struct umb_softc *, struct usb_config *);
176
static void	 umb_close_bulkpipes(struct umb_softc *);
177
static int	 umb_ioctl(struct ifnet *, u_long, caddr_t);
178
static void	 umb_init(void *);
179
#ifdef DEV_NETMAP
180
static void	 umb_input(struct ifnet *, struct mbuf *);
181
#endif
182
static int	 umb_output(struct ifnet *, struct mbuf *,
183
		    const struct sockaddr *, struct route *);
184
static void	 umb_start(struct ifnet *);
185
static void	 umb_start_task(struct usb_proc_msg *);
186
#if 0
187
static void	 umb_watchdog(struct ifnet *);
188
#endif
189
static void	 umb_statechg_timeout(void *);
190
191
static int	 umb_mediachange(struct ifnet *);
192
static void	 umb_mediastatus(struct ifnet *, struct ifmediareq *);
193
194
static void	 umb_add_task(struct umb_softc *sc, usb_proc_callback_t,
195
		    struct usb_proc_msg *, struct usb_proc_msg *, int);
196
static void	 umb_newstate(struct umb_softc *, enum umb_state, int);
197
static void	 umb_state_task(struct usb_proc_msg *);
198
static void	 umb_up(struct umb_softc *);
199
static void	 umb_down(struct umb_softc *, int);
200
201
static void	 umb_get_response_task(struct usb_proc_msg *);
202
203
static void	 umb_decode_response(struct umb_softc *, void *, int);
204
static void	 umb_handle_indicate_status_msg(struct umb_softc *, void *,
205
		    int);
206
static void	 umb_handle_opendone_msg(struct umb_softc *, void *, int);
207
static void	 umb_handle_closedone_msg(struct umb_softc *, void *, int);
208
static int	 umb_decode_register_state(struct umb_softc *, void *, int);
209
static int	 umb_decode_devices_caps(struct umb_softc *, void *, int);
210
static int	 umb_decode_subscriber_status(struct umb_softc *, void *, int);
211
static int	 umb_decode_radio_state(struct umb_softc *, void *, int);
212
static int	 umb_decode_pin(struct umb_softc *, void *, int);
213
static int	 umb_decode_packet_service(struct umb_softc *, void *, int);
214
static int	 umb_decode_signal_state(struct umb_softc *, void *, int);
215
static int	 umb_decode_connect_info(struct umb_softc *, void *, int);
216
static int	 umb_decode_ip_configuration(struct umb_softc *, void *, int);
217
static void	 umb_rx(struct umb_softc *);
218
static usb_callback_t umb_rxeof;
219
static void	 umb_rxflush(struct umb_softc *);
220
static int	 umb_encap(struct umb_softc *, struct mbuf *, struct usb_xfer *);
221
static usb_callback_t umb_txeof;
222
static void	 umb_txflush(struct umb_softc *);
223
static void	 umb_decap(struct umb_softc *, struct usb_xfer *, int);
224
225
static usb_error_t	 umb_send_encap_command(struct umb_softc *, void *, int);
226
static int	 umb_get_encap_response(struct umb_softc *, void *, int *);
227
static void	 umb_ctrl_msg(struct umb_softc *, uint32_t, void *, int);
228
229
static void	 umb_open(struct umb_softc *);
230
static void	 umb_close(struct umb_softc *);
231
232
static int	 umb_setpin(struct umb_softc *, int, int, void *, int, void *,
233
		    int);
234
static void	 umb_setdataclass(struct umb_softc *);
235
static void	 umb_radio(struct umb_softc *, int);
236
static void	 umb_allocate_cid(struct umb_softc *);
237
static void	 umb_send_fcc_auth(struct umb_softc *);
238
static void	 umb_packet_service(struct umb_softc *, int);
239
static void	 umb_connect(struct umb_softc *);
240
static void	 umb_disconnect(struct umb_softc *);
241
static void	 umb_send_connect(struct umb_softc *, int);
242
243
static void	 umb_qry_ipconfig(struct umb_softc *);
244
static void	 umb_cmd(struct umb_softc *, int, int, const void *, int);
245
static void	 umb_cmd1(struct umb_softc *, int, int, const void *, int, uint8_t *);
246
static void	 umb_command_done(struct umb_softc *, void *, int);
247
static void	 umb_decode_cid(struct umb_softc *, uint32_t, void *, int);
248
static void	 umb_decode_qmi(struct umb_softc *, uint8_t *, int);
249
250
static usb_callback_t umb_intr;
251
252
static char	*umb_ntop(struct sockaddr *);
253
254
static const int umb_xfer_tout = USB_DEFAULT_TIMEOUT;
255
256
static uint8_t	 umb_uuid_basic_connect[] = MBIM_UUID_BASIC_CONNECT;
257
static uint8_t	 umb_uuid_context_internet[] = MBIM_UUID_CONTEXT_INTERNET;
258
static uint8_t	 umb_uuid_qmi_mbim[] = MBIM_UUID_QMI_MBIM;
259
static uint32_t	 umb_session_id = 0;
260
261
static const struct usb_config umb_config[UMB_N_TRANSFER] = {
262
	[UMB_INTR_RX] = {
263
		.type = UE_INTERRUPT,
264
		.endpoint = UE_ADDR_ANY,
265
		.direction = UE_DIR_IN,
266
		.if_index = 1,
267
		.callback = umb_intr,
268
		.bufsize = sizeof (struct usb_cdc_notification),
269
		.flags = {.pipe_bof = 1,.short_xfer_ok = 1},
270
		.usb_mode = USB_MODE_HOST,
271
	},
272
	[UMB_BULK_RX] = {
273
		.type = UE_BULK,
274
		.endpoint = UE_ADDR_ANY,
275
		.direction = UE_DIR_IN,
276
		.if_index = 0,
277
		.callback = umb_rxeof,
278
		.bufsize = 8 * 1024,
279
		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.ext_buffer = 1},
280
		.usb_mode = USB_MODE_HOST,
281
	},
282
	[UMB_BULK_TX] = {
283
		.type = UE_BULK,
284
		.endpoint = UE_ADDR_ANY,
285
		.direction = UE_DIR_OUT,
286
		.if_index = 0,
287
		.callback = umb_txeof,
288
		.bufsize = 8 * 1024,
289
		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1},
290
		.timeout = umb_xfer_tout,
291
		.usb_mode = USB_MODE_HOST,
292
	},
293
};
294
295
static device_method_t umb_methods[] = {
296
	/* USB interface */
297
	DEVMETHOD(usb_handle_request, umb_handle_request),
298
299
	/* Device interface */
300
	DEVMETHOD(device_probe, umb_probe),
301
	DEVMETHOD(device_attach, umb_attach),
302
	DEVMETHOD(device_detach, umb_detach),
303
	DEVMETHOD(device_suspend, umb_suspend),
304
	DEVMETHOD(device_resume, umb_resume),
305
306
	DEVMETHOD_END
307
};
308
309
static driver_t umb_driver = {
310
	.name = "umb",
311
	.methods = umb_methods,
312
	.size = sizeof (struct umb_softc),
313
};
314
315
MALLOC_DEFINE(M_USB_UMB, "USB UMB", "USB MBIM driver");
316
317
const int umb_delay = 4000;
318
319
/*
320
 * These devices require an "FCC Authentication" command.
321
 */
322
#ifndef USB_VENDOR_SIERRA
323
# define USB_VENDOR_SIERRA	0x1199
324
#endif
325
#ifndef USB_PRODUCT_SIERRA_EM7455
326
# define USB_PRODUCT_SIERRA_EM7455	0x9079
327
#endif
328
const struct usb_device_id umb_fccauth_devs[] = {
329
	{
330
		.match_flag_vendor = 1,
331
		.match_flag_product = 1,
332
		.idVendor = USB_VENDOR_SIERRA,
333
		.idProduct = USB_PRODUCT_SIERRA_EM7455
334
	}
335
};
336
337
static const uint8_t umb_qmi_alloc_cid[] = {
338
	0x01,
339
	0x0f, 0x00,		/* len */
340
	0x00,			/* QMUX flags */
341
	0x00,			/* service "ctl" */
342
	0x00,			/* CID */
343
	0x00,			/* QMI flags */
344
	0x01,			/* transaction */
345
	0x22, 0x00,		/* msg "Allocate CID" */
346
	0x04, 0x00,		/* TLV len */
347
	0x01, 0x01, 0x00, 0x02	/* TLV */
348
};
349
350
static const uint8_t umb_qmi_fcc_auth[] = {
351
	0x01,
352
	0x0c, 0x00,		/* len */
353
	0x00,			/* QMUX flags */
354
	0x02,			/* service "dms" */
355
#define UMB_QMI_CID_OFFS	5
356
	0x00,			/* CID (filled in later) */
357
	0x00,			/* QMI flags */
358
	0x01, 0x00,		/* transaction */
359
	0x5f, 0x55,		/* msg "Send FCC Authentication" */
360
	0x00, 0x00		/* TLV len */
361
};
362
363
static int
364
umb_probe(device_t dev)
365
{
366
	struct usb_attach_arg *uaa = device_get_ivars(dev);
367
	usb_interface_descriptor_t *id;
368
369
	if (uaa->usb_mode != USB_MODE_HOST)
370
		return (ENXIO);
371
	if ((id = usbd_get_interface_descriptor(uaa->iface)) == NULL)
372
		return (ENXIO);
373
374
	/*
375
	 * If this function implements NCM, check if alternate setting
376
	 * 1 implements MBIM.
377
	 */
378
	if (id->bInterfaceClass == UICLASS_CDC &&
379
	    id->bInterfaceSubClass ==
380
	    UISUBCLASS_NETWORK_CONTROL_MODEL) {
381
		id = usbd_get_interface_descriptor(
382
				usbd_get_iface(uaa->device,
383
					uaa->info.bIfaceIndex + 1));
384
		if (id == NULL || id->bAlternateSetting != 1)
385
			return (ENXIO);
386
	}
387
388
#ifndef UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL
389
# define UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL 14
390
#endif
391
	if (id->bInterfaceClass == UICLASS_CDC &&
392
	    id->bInterfaceSubClass ==
393
	    UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL &&
394
	    id->bInterfaceProtocol == 0)
395
		return (BUS_PROBE_SPECIFIC);
396
397
	return (ENXIO);
398
}
399
400
static int
401
umb_attach(device_t dev)
402
{
403
	struct umb_softc *sc = device_get_softc(dev);
404
	struct usb_attach_arg *uaa = device_get_ivars(dev);
405
	struct usb_config config[UMB_N_TRANSFER];
406
	int	 v;
407
	const struct usb_cdc_union_descriptor *ud;
408
	const struct mbim_descriptor *md;
409
	int	 i;
410
	usb_interface_descriptor_t *id;
411
	struct usb_interface *iface;
412
	int	 data_ifaceno = -1;
413
	usb_error_t error;
414
415
	sc->sc_dev = dev;
416
	sc->sc_udev = uaa->device;
417
418
	memcpy(config, umb_config, sizeof (config));
419
420
	device_set_usb_desc(dev);
421
422
	sc->sc_ctrl_ifaceno = uaa->info.bIfaceNum;
423
424
	mtx_init(&sc->sc_mutex, device_get_nameunit(dev), NULL, MTX_DEF);
425
426
	/*
427
	 * Some MBIM hardware does not provide the mandatory CDC Union
428
	 * Descriptor, so we also look at matching Interface
429
	 * Association Descriptors to find out the MBIM Data Interface
430
	 * number.
431
	 */
432
	sc->sc_ver_maj = sc->sc_ver_min = -1;
433
	sc->sc_maxpktlen = MBIM_MAXSEGSZ_MINVAL;
434
	id = usbd_get_interface_descriptor(uaa->iface);
435
436
	ud = usbd_find_descriptor(sc->sc_udev, id, uaa->info.bIfaceIndex,
437
			UDESC_CS_INTERFACE, 0xff, UDESCSUB_CDC_UNION, 0xff);
438
	if (ud != NULL) {
439
		data_ifaceno = ud->bSlaveInterface[0];
440
	}
441
442
	md = usbd_find_descriptor(sc->sc_udev, id, uaa->info.bIfaceIndex,
443
			UDESC_CS_INTERFACE, 0xff, UDESCSUB_MBIM, 0xff);
444
	if (md != NULL) {
445
		v = UGETW(md->bcdMBIMVersion);
446
		sc->sc_ver_maj = MBIM_VER_MAJOR(v);
447
		sc->sc_ver_min = MBIM_VER_MINOR(v);
448
		sc->sc_ctrl_len = UGETW(md->wMaxControlMessage);
449
		/* Never trust a USB device! Could try to exploit us */
450
		if (sc->sc_ctrl_len < MBIM_CTRLMSG_MINLEN ||
451
				sc->sc_ctrl_len > MBIM_CTRLMSG_MAXLEN) {
452
			DPRINTF("control message len %d out of "
453
					"bounds [%d .. %d]\n",
454
					sc->sc_ctrl_len, MBIM_CTRLMSG_MINLEN,
455
					MBIM_CTRLMSG_MAXLEN);
456
			/* continue anyway */
457
		}
458
		sc->sc_maxpktlen = UGETW(md->wMaxSegmentSize);
459
		DPRINTFN(2, "ctrl_len=%d, maxpktlen=%d, cap=0x%x\n",
460
				sc->sc_ctrl_len, sc->sc_maxpktlen,
461
				md->bmNetworkCapabilities);
462
	}
463
	if (sc->sc_ver_maj < 0) {
464
		device_printf(dev, "error: missing MBIM descriptor\n");
465
		goto fail;
466
	}
467
468
	device_printf(dev, "version %d.%d\n", sc->sc_ver_maj,
469
	    sc->sc_ver_min);
470
471
	if (usbd_lookup_id_by_uaa(umb_fccauth_devs, sizeof (umb_fccauth_devs),
472
				  uaa)) {
473
		sc->sc_flags |= UMBFLG_FCC_AUTH_REQUIRED;
474
		sc->sc_cid = -1;
475
	}
476
477
	for (i = 0; i < sc->sc_udev->ifaces_max; i++) {
478
		iface = usbd_get_iface(sc->sc_udev, i);
479
		id = usbd_get_interface_descriptor(iface);
480
		if (id == NULL)
481
			break;
482
483
		if (id->bInterfaceNumber == data_ifaceno) {
484
			sc->sc_data_iface = iface;
485
			sc->sc_ifaces_index[0] = i;
486
			sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
487
			break;
488
		}
489
	}
490
	if (sc->sc_data_iface == NULL) {
491
		device_printf(dev, "error: no data interface found\n");
492
		goto fail;
493
	}
494
495
	/*
496
	 * If this is a combined NCM/MBIM function, switch to
497
	 * alternate setting one to enable MBIM.
498
	 */
499
	id = usbd_get_interface_descriptor(uaa->iface);
500
	if (id != NULL && id->bInterfaceClass == UICLASS_CDC &&
501
	    id->bInterfaceSubClass == UISUBCLASS_NETWORK_CONTROL_MODEL) {
502
		device_printf(sc->sc_dev, "combined NCM/MBIM\n");
503
		error = usbd_req_set_alt_interface_no(sc->sc_udev,
504
				NULL, uaa->info.bIfaceIndex, 1);
505
		if (error != USB_ERR_NORMAL_COMPLETION) {
506
			device_printf(dev, "error: Could not switch to"
507
					   " alternate setting for MBIM\n");
508
			goto fail;
509
		}
510
		sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex + 1;
511
	}
512
513
	if (usb_proc_create(&sc->sc_taskqueue, &sc->sc_mutex,
514
				device_get_nameunit(sc->sc_dev),
515
				USB_PRI_MED) != 0)
516
		goto fail;
517
518
	DPRINTFN(2, "ctrl-ifno#%d: data-ifno#%d\n", sc->sc_ctrl_ifaceno,
519
	    data_ifaceno);
520
521
	usb_callout_init_mtx(&sc->sc_statechg_timer, &sc->sc_mutex, 0);
522
523
	umb_ncm_setup(sc, config);
524
	DPRINTFN(2, "%s: rx/tx size %d/%d\n", DEVNAM(sc),
525
			sc->sc_rx_bufsz, sc->sc_tx_bufsz);
526
527
	sc->sc_rx_buf = malloc(sc->sc_rx_bufsz, M_DEVBUF, M_WAITOK);
528
	sc->sc_tx_buf = malloc(sc->sc_tx_bufsz, M_DEVBUF, M_WAITOK);
529
530
	for (i = 0; i != 32; i++) {
531
		error = usbd_set_alt_interface_index(sc->sc_udev,
532
				sc->sc_ifaces_index[0], i);
533
		if (error)
534
			break;
535
536
		error = usbd_transfer_setup(sc->sc_udev, sc->sc_ifaces_index,
537
				sc->sc_xfer, config, UMB_N_TRANSFER,
538
				sc, &sc->sc_mutex);
539
		if (error == USB_ERR_NORMAL_COMPLETION)
540
			break;
541
	}
542
	if (error || (i == 32)) {
543
		device_printf(sc->sc_dev, "error: failed to setup xfers\n");
544
		goto fail;
545
	}
546
547
	sc->sc_resp_buf = malloc(sc->sc_ctrl_len, M_DEVBUF, M_WAITOK);
548
	sc->sc_ctrl_msg = malloc(sc->sc_ctrl_len, M_DEVBUF, M_WAITOK);
549
550
	sc->sc_info.regstate = MBIM_REGSTATE_UNKNOWN;
551
	sc->sc_info.pin_attempts_left = UMB_VALUE_UNKNOWN;
552
	sc->sc_info.rssi = UMB_VALUE_UNKNOWN;
553
	sc->sc_info.ber = UMB_VALUE_UNKNOWN;
554
555
	/* defer attaching the interface */
556
	mtx_lock(&sc->sc_mutex);
557
	umb_add_task(sc, umb_attach_task,
558
			&sc->sc_proc_attach_task[0].hdr,
559
			&sc->sc_proc_attach_task[1].hdr, 0);
560
	mtx_unlock(&sc->sc_mutex);
561
562
	return (0);
563
564
fail:
565
	umb_detach(sc->sc_dev);
566
	return (ENXIO);
567
}
568
569
static void
570
umb_attach_task(struct usb_proc_msg *msg)
571
{
572
	struct umb_task *task = (struct umb_task *)msg;
573
	struct umb_softc *sc = task->sc;
574
	struct ifnet *ifp;
575
576
	mtx_unlock(&sc->sc_mutex);
577
578
	CURVNET_SET_QUIET(vnet0);
579
580
	/* initialize the interface */
581
	sc->sc_if = ifp = if_alloc(IFT_MBIM);
582
	if_initname(ifp, "umb", device_get_unit(sc->sc_dev));
583
584
	if_setsoftc(ifp, sc);
585
	if_setflags(ifp, IFF_SIMPLEX | IFF_MULTICAST | IFF_POINTOPOINT);
586
	if_setioctlfn(ifp, umb_ioctl);
587
#ifdef DEV_NETMAP
588
	if_setinputfn(ifp, umb_input);
589
#endif
590
	if_setoutputfn(ifp, umb_output);
591
	ifp->if_start = umb_start;
592
	if_setinitfn(ifp, umb_init);
593
594
#if 0
595
	ifp->if_watchdog = umb_watchdog;
596
#endif
597
	ifp->if_link_state = LINK_STATE_DOWN;
598
	ifmedia_init(&sc->sc_im, 0, umb_mediachange, umb_mediastatus);
599
	ifmedia_add(&sc->sc_im, IFM_NONE | IFM_AUTO, 0, NULL);
600
601
	ifp->if_addrlen = 0;
602
	ifp->if_hdrlen = sizeof (struct ncm_header16) +
603
	    sizeof (struct ncm_pointer16);
604
	/* XXX hard-coded atm */
605
	if_setmtu(ifp, MIN(2048, sc->sc_maxpktlen));
606
	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
607
	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
608
	IFQ_SET_READY(&ifp->if_snd);
609
610
	/* attach the interface */
611
	if_attach(ifp);
612
	bpfattach(ifp, DLT_RAW, 0);
613
614
	sc->sc_attached = 1;
615
616
	CURVNET_RESTORE();
617
618
	umb_init(sc);
619
	mtx_lock(&sc->sc_mutex);
620
}
621
622
static int
623
umb_detach(device_t dev)
624
{
625
	struct umb_softc *sc = device_get_softc(dev);
626
	struct ifnet *ifp = GET_IFP(sc);
627
628
	usb_proc_drain(&sc->sc_taskqueue);
629
630
	mtx_lock(&sc->sc_mutex);
631
	if (ifp != NULL && (ifp->if_drv_flags & IFF_DRV_RUNNING))
632
		umb_down(sc, 1);
633
	umb_close(sc);
634
	mtx_unlock(&sc->sc_mutex);
635
636
	usbd_transfer_unsetup(sc->sc_xfer, UMB_N_TRANSFER);
637
638
	free(sc->sc_tx_buf, M_DEVBUF);
639
	free(sc->sc_rx_buf, M_DEVBUF);
640
641
	usb_callout_drain(&sc->sc_statechg_timer);
642
643
	usb_proc_free(&sc->sc_taskqueue);
644
645
	mtx_destroy(&sc->sc_mutex);
646
647
	free(sc->sc_ctrl_msg, M_DEVBUF);
648
	free(sc->sc_resp_buf, M_DEVBUF);
649
650
	if (ifp != NULL && ifp->if_softc) {
651
		ifmedia_removeall(&sc->sc_im);
652
	}
653
	if (sc->sc_attached) {
654
		bpfdetach(ifp);
655
		if_detach(ifp);
656
		if_free(ifp);
657
		sc->sc_if = NULL;
658
	}
659
660
	return 0;
661
}
662
663
static void
664
umb_ncm_setup(struct umb_softc *sc, struct usb_config * config)
665
{
666
	usb_device_request_t req;
667
	struct ncm_ntb_parameters np;
668
	usb_error_t error;
669
670
	/* Query NTB tranfers sizes */
671
	req.bmRequestType = UT_READ_CLASS_INTERFACE;
672
	req.bRequest = NCM_GET_NTB_PARAMETERS;
673
	USETW(req.wValue, 0);
674
	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
675
	USETW(req.wLength, sizeof (np));
676
	mtx_lock(&sc->sc_mutex);
677
	error = usbd_do_request(sc->sc_udev, &sc->sc_mutex, &req, &np);
678
	mtx_unlock(&sc->sc_mutex);
679
	if (error == USB_ERR_NORMAL_COMPLETION &&
680
	    UGETW(np.wLength) == sizeof (np)) {
681
		config[UMB_BULK_RX].bufsize = UGETDW(np.dwNtbInMaxSize);
682
		config[UMB_BULK_TX].bufsize = UGETDW(np.dwNtbOutMaxSize);
683
	}
684
	sc->sc_rx_bufsz = config[UMB_BULK_RX].bufsize;
685
	sc->sc_tx_bufsz = config[UMB_BULK_TX].bufsize;
686
}
687
688
static int
689
umb_handle_request(device_t dev,
690
    const void *preq, void **pptr, uint16_t *plen,
691
    uint16_t offset, uint8_t *pstate)
692
{
693
	/* FIXME really implement */
694
695
	return (ENXIO);
696
}
697
698
static int
699
umb_suspend(device_t dev)
700
{
701
	device_printf(dev, "Suspending\n");
702
	return (0);
703
}
704
705
static int
706
umb_resume(device_t dev)
707
{
708
	device_printf(dev, "Resuming\n");
709
	return (0);
710
}
711
712
static int
713
umb_deactivate(device_t dev)
714
{
715
	struct umb_softc *sc = device_get_softc(dev);
716
	struct ifnet *ifp = GET_IFP(sc);
717
718
	if (ifp != NULL) {
719
		if_dead(ifp);
720
	}
721
	sc->sc_dying = 1;
722
	return 0;
723
}
724
725
static void
726
umb_close_bulkpipes(struct umb_softc *sc)
727
{
728
	struct ifnet *ifp = GET_IFP(sc);
729
730
	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
731
732
	umb_rxflush(sc);
733
	umb_txflush(sc);
734
735
	usbd_transfer_stop(sc->sc_xfer[UMB_BULK_RX]);
736
	usbd_transfer_stop(sc->sc_xfer[UMB_BULK_TX]);
737
}
738
739
static int
740
umb_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
741
{
742
	struct umb_softc *sc = ifp->if_softc;
743
	struct in_ifaddr *ia = (struct in_ifaddr *)data;
744
	struct ifreq *ifr = (struct ifreq *)data;
745
	int error = 0;
746
	struct umb_parameter mp;
747
748
	if (sc->sc_dying)
749
		return EIO;
750
751
	switch (cmd) {
752
	case SIOCSIFADDR:
753
		switch (ia->ia_ifa.ifa_addr->sa_family) {
754
		case AF_INET:
755
			break;
756
#ifdef INET6
757
		case AF_INET6:
758
			break;
759
#endif /* INET6 */
760
		default:
761
			error = EAFNOSUPPORT;
762
			break;
763
		}
764
		break;
765
	case SIOCSIFFLAGS:
766
		mtx_lock(&sc->sc_mutex);
767
		umb_add_task(sc, umb_state_task,
768
				&sc->sc_proc_state_task[0].hdr,
769
				&sc->sc_proc_state_task[1].hdr, 1);
770
		mtx_unlock(&sc->sc_mutex);
771
		break;
772
	case SIOCGUMBINFO:
773
		error = copyout(&sc->sc_info, ifr->ifr_ifru.ifru_data,
774
		    sizeof (sc->sc_info));
775
		break;
776
	case SIOCSUMBPARAM:
777
		error = priv_check(curthread, PRIV_NET_SETIFPHYS);
778
		if (error)
779
			break;
780
781
		if ((error = copyin(ifr->ifr_ifru.ifru_data, &mp, sizeof (mp))) != 0)
782
			break;
783
784
		if ((error = umb_setpin(sc, mp.op, mp.is_puk, mp.pin, mp.pinlen,
785
		    mp.newpin, mp.newpinlen)) != 0)
786
			break;
787
788
		if (mp.apnlen < 0 || mp.apnlen > sizeof (sc->sc_info.apn)) {
789
			error = EINVAL;
790
			break;
791
		}
792
		sc->sc_roaming = mp.roaming ? 1 : 0;
793
		memset(sc->sc_info.apn, 0, sizeof (sc->sc_info.apn));
794
		memcpy(sc->sc_info.apn, mp.apn, mp.apnlen);
795
		sc->sc_info.apnlen = mp.apnlen;
796
		memset(sc->sc_info.username, 0, sizeof (sc->sc_info.username));
797
		memcpy(sc->sc_info.username, mp.username, mp.usernamelen);
798
		sc->sc_info.usernamelen = mp.usernamelen;
799
		memset(sc->sc_info.password, 0, sizeof (sc->sc_info.password));
800
		memcpy(sc->sc_info.password, mp.password, mp.passwordlen);
801
		sc->sc_info.passwordlen = mp.passwordlen;
802
		sc->sc_info.preferredclasses = mp.preferredclasses;
803
		umb_setdataclass(sc);
804
		break;
805
	case SIOCGUMBPARAM:
806
		memset(&mp, 0, sizeof (mp));
807
		memcpy(mp.apn, sc->sc_info.apn, sc->sc_info.apnlen);
808
		mp.apnlen = sc->sc_info.apnlen;
809
		mp.roaming = sc->sc_roaming;
810
		mp.preferredclasses = sc->sc_info.preferredclasses;
811
		error = copyout(&mp, ifr->ifr_ifru.ifru_data, sizeof (mp));
812
		break;
813
	case SIOCSIFMTU:
814
		/* Does this include the NCM headers and tail? */
815
		if (ifr->ifr_mtu > ifp->if_mtu) {
816
			error = EINVAL;
817
			break;
818
		}
819
		ifp->if_mtu = ifr->ifr_mtu;
820
		break;
821
	case SIOCAIFADDR:
822
	case SIOCSIFDSTADDR:
823
	case SIOCADDMULTI:
824
	case SIOCDELMULTI:
825
		break;
826
	case SIOCGIFMEDIA:
827
		error = ifmedia_ioctl(ifp, ifr, &sc->sc_im, cmd);
828
		break;
829
	default:
830
		error = EINVAL;
831
		break;
832
	}
833
	return (error);
834
}
835
836
static void
837
umb_init(void *arg)
838
{
839
	struct umb_softc *sc = arg;
840
841
	mtx_lock(&sc->sc_mutex);
842
	umb_add_task(sc, umb_start_task,
843
			&sc->sc_proc_start_task[0].hdr,
844
			&sc->sc_proc_start_task[1].hdr, 0);
845
	mtx_unlock(&sc->sc_mutex);
846
}
847
848
static void
849
umb_input(struct ifnet *ifp, struct mbuf *m)
850
{
851
	struct mbuf *mn;
852
	struct epoch_tracker et;
853
854
	while (m) {
855
		mn = m->m_nextpkt;
856
		m->m_nextpkt = NULL;
857
858
		NET_EPOCH_ENTER(et);
859
		BPF_MTAP(ifp, m);
860
861
		CURVNET_SET_QUIET(vnet0);
862
863
		netisr_dispatch(NETISR_IP, m);
864
		m = mn;
865
866
		CURVNET_RESTORE();
867
		NET_EPOCH_EXIT(et);
868
	}
869
}
870
871
static int
872
umb_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
873
    struct route *rtp)
874
{
875
	int error;
876
877
	DPRINTFN(10, "%s: enter\n", __func__);
878
879
	switch (dst->sa_family) {
880
#ifdef INET6
881
	case AF_INET6:
882
		/* fall through */
883
#endif
884
	case AF_INET:
885
		break;
886
887
		/* silently drop dhclient packets */
888
	case AF_UNSPEC:
889
		m_freem(m);
890
		return (0);
891
892
		/* drop other packet types */
893
	default:
894
		m_freem(m);
895
		return (EAFNOSUPPORT);
896
	}
897
898
	/*
899
	 * Queue message on interface, and start output if interface
900
	 * not yet active.
901
	 */
902
	error = (ifp->if_transmit)(ifp, m);
903
	if (error) {
904
		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
905
		return (ENOBUFS);
906
	}
907
908
	return (0);
909
}
910
911
static void
912
umb_start(struct ifnet *ifp)
913
{
914
	struct umb_softc *sc = ifp->if_softc;
915
916
	if (sc->sc_dying || !(ifp->if_drv_flags & IFF_DRV_RUNNING))
917
		return;
918
919
	mtx_lock(&sc->sc_mutex);
920
	usbd_transfer_start(sc->sc_xfer[UMB_BULK_TX]);
921
	mtx_unlock(&sc->sc_mutex);
922
}
923
924
static void
925
umb_start_task(struct usb_proc_msg *msg)
926
{
927
	struct umb_task *task = (struct umb_task *)msg;
928
	struct umb_softc *sc = task->sc;
929
	struct ifnet *ifp = GET_IFP(sc);
930
931
	DPRINTF("%s()\n", __func__);
932
933
	mtx_assert(&sc->sc_mutex, MA_OWNED);
934
935
	ifp->if_drv_flags |= IFF_DRV_RUNNING;
936
937
	/* start interrupt transfer */
938
	usbd_transfer_start(sc->sc_xfer[UMB_INTR_RX]);
939
940
	umb_open(sc);
941
}
942
943
#if 0
944
static void
945
umb_watchdog(struct ifnet *ifp)
946
{
947
	struct umb_softc *sc = ifp->if_softc;
948
949
	if (sc->sc_dying)
950
		return;
951
952
	if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
953
	device_printf(sc->sc_dev, "watchdog timeout\n");
954
	usbd_transfer_drain(sc->sc_xfer[UMB_BULK_TX]);
955
	return;
956
}
957
#endif
958
959
static void
960
umb_statechg_timeout(void *arg)
961
{
962
	struct umb_softc *sc = arg;
963
	struct ifnet *ifp = GET_IFP(sc);
964
965
	mtx_assert(&sc->sc_mutex, MA_OWNED);
966
967
	if (sc->sc_info.regstate != MBIM_REGSTATE_ROAMING || sc->sc_roaming)
968
		if (ifp->if_flags & IFF_DEBUG)
969
			log(LOG_DEBUG, "%s: state change timeout\n",
970
					DEVNAM(sc));
971
972
	umb_add_task(sc, umb_state_task,
973
			&sc->sc_proc_state_task[0].hdr,
974
			&sc->sc_proc_state_task[1].hdr, 0);
975
}
976
977
static int
978
umb_mediachange(struct ifnet * ifp)
979
{
980
	return 0;
981
}
982
983
static void
984
umb_mediastatus(struct ifnet * ifp, struct ifmediareq * imr)
985
{
986
	switch (ifp->if_link_state) {
987
	case LINK_STATE_UP:
988
		imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
989
		break;
990
	case LINK_STATE_DOWN:
991
		imr->ifm_status = IFM_AVALID;
992
		break;
993
	default:
994
		imr->ifm_status = 0;
995
		break;
996
	}
997
}
998
999
static void
1000
umb_add_task(struct umb_softc *sc, usb_proc_callback_t callback,
1001
		struct usb_proc_msg *t0, struct usb_proc_msg *t1, int sync)
1002
{
1003
	struct umb_task * task;
1004
1005
	mtx_assert(&sc->sc_mutex, MA_OWNED);
1006
1007
	if (usb_proc_is_gone(&sc->sc_taskqueue)) {
1008
		return;
1009
	}
1010
1011
	task = usb_proc_msignal(&sc->sc_taskqueue, t0, t1);
1012
1013
	task->hdr.pm_callback = callback;
1014
	task->sc = sc;
1015
1016
	if (sync) {
1017
		usb_proc_mwait(&sc->sc_taskqueue, t0, t1);
1018
	}
1019
}
1020
1021
static void
1022
umb_newstate(struct umb_softc *sc, enum umb_state newstate, int flags)
1023
{
1024
	struct ifnet *ifp = GET_IFP(sc);
1025
1026
	if (newstate == sc->sc_state)
1027
		return;
1028
	if (((flags & UMB_NS_DONT_DROP) && newstate < sc->sc_state) ||
1029
	    ((flags & UMB_NS_DONT_RAISE) && newstate > sc->sc_state))
1030
		return;
1031
	if (ifp->if_flags & IFF_DEBUG)
1032
		log(LOG_DEBUG, "%s: state going %s from '%s' to '%s'\n",
1033
		    DEVNAM(sc), newstate > sc->sc_state ? "up" : "down",
1034
		    umb_istate(sc->sc_state), umb_istate(newstate));
1035
	sc->sc_state = newstate;
1036
	umb_add_task(sc, umb_state_task,
1037
			&sc->sc_proc_state_task[0].hdr,
1038
			&sc->sc_proc_state_task[1].hdr, 0);
1039
}
1040
1041
static void
1042
umb_state_task(struct usb_proc_msg *msg)
1043
{
1044
	struct umb_task *task = (struct umb_task *)msg;
1045
	struct umb_softc *sc = task->sc;
1046
	struct ifnet *ifp = GET_IFP(sc);
1047
	struct ifreq ifr;
1048
	int	 state;
1049
1050
	DPRINTF("%s()\n", __func__);
1051
1052
	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
1053
		/*
1054
		 * Query the registration state until we're with the home
1055
		 * network again.
1056
		 */
1057
		umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY, NULL, 0);
1058
		return;
1059
	}
1060
1061
	if (ifp->if_flags & IFF_UP)
1062
		umb_up(sc);
1063
	else
1064
		umb_down(sc, 0);
1065
1066
	state = (sc->sc_state == UMB_S_UP) ? LINK_STATE_UP : LINK_STATE_DOWN;
1067
	if (ifp->if_link_state != state) {
1068
		if (ifp->if_flags & IFF_DEBUG)
1069
			log(LOG_DEBUG, "%s: link state changed from %s to %s\n",
1070
			    DEVNAM(sc),
1071
			    (ifp->if_link_state == LINK_STATE_UP)
1072
			    ? "up" : "down",
1073
			    (state == LINK_STATE_UP) ? "up" : "down");
1074
		ifp->if_link_state = state;
1075
		if (state != LINK_STATE_UP) {
1076
			/*
1077
			 * Purge any existing addresses
1078
			 */
1079
			memset(sc->sc_info.ipv4dns, 0,
1080
			    sizeof (sc->sc_info.ipv4dns));
1081
			mtx_unlock(&sc->sc_mutex);
1082
			CURVNET_SET_QUIET(vnet0);
1083
			if (in_control(NULL, SIOCGIFADDR, (caddr_t)&ifr, ifp,
1084
				       curthread) == 0 &&
1085
			    satosin(&ifr.ifr_addr)->sin_addr.s_addr !=
1086
			    INADDR_ANY) {
1087
				in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr,
1088
					   ifp, curthread);
1089
			}
1090
			CURVNET_RESTORE();
1091
			mtx_lock(&sc->sc_mutex);
1092
		}
1093
		if_link_state_change(ifp, state);
1094
	}
1095
}
1096
1097
static void
1098
umb_up(struct umb_softc *sc)
1099
{
1100
	struct ifnet *ifp = GET_IFP(sc);
1101
1102
	switch (sc->sc_state) {
1103
	case UMB_S_DOWN:
1104
		DPRINTF("init: opening ...\n");
1105
		umb_open(sc);
1106
		break;
1107
	case UMB_S_OPEN:
1108
		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED) {
1109
			if (sc->sc_cid == -1) {
1110
				DPRINTF("init: allocating CID ...\n");
1111
				umb_allocate_cid(sc);
1112
				break;
1113
			} else
1114
				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
1115
		} else {
1116
			DPRINTF("init: turning radio on ...\n");
1117
			umb_radio(sc, 1);
1118
			break;
1119
		}
1120
		/*FALLTHROUGH*/
1121
	case UMB_S_CID:
1122
		DPRINTF("init: sending FCC auth ...\n");
1123
		umb_send_fcc_auth(sc);
1124
		break;
1125
	case UMB_S_RADIO:
1126
		DPRINTF("init: checking SIM state ...\n");
1127
		umb_cmd(sc, MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CMDOP_QRY,
1128
		    NULL, 0);
1129
		break;
1130
	case UMB_S_SIMREADY:
1131
		DPRINTF("init: attaching ...\n");
1132
		umb_packet_service(sc, 1);
1133
		break;
1134
	case UMB_S_ATTACHED:
1135
		sc->sc_tx_seq = 0;
1136
		DPRINTF("init: connecting ...\n");
1137
		umb_connect(sc);
1138
		break;
1139
	case UMB_S_CONNECTED:
1140
		DPRINTF("init: getting IP config ...\n");
1141
		umb_qry_ipconfig(sc);
1142
		break;
1143
	case UMB_S_UP:
1144
		DPRINTF("init: reached state UP\n");
1145
		if (!(ifp->if_flags & IFF_DRV_RUNNING)) {
1146
			ifp->if_drv_flags |= IFF_DRV_RUNNING;
1147
			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1148
			umb_rx(sc);
1149
		}
1150
		break;
1151
	}
1152
	if (sc->sc_state < UMB_S_UP)
1153
		usb_callout_reset(&sc->sc_statechg_timer,
1154
		    UMB_STATE_CHANGE_TIMEOUT * hz, umb_statechg_timeout, sc);
1155
	else {
1156
		usb_callout_stop(&sc->sc_statechg_timer);
1157
	}
1158
	return;
1159
}
1160
1161
static void
1162
umb_down(struct umb_softc *sc, int force)
1163
{
1164
	umb_close_bulkpipes(sc);
1165
1166
	switch (sc->sc_state) {
1167
	case UMB_S_UP:
1168
	case UMB_S_CONNECTED:
1169
		DPRINTF("stop: disconnecting ...\n");
1170
		umb_disconnect(sc);
1171
		if (!force)
1172
			break;
1173
		/*FALLTHROUGH*/
1174
	case UMB_S_ATTACHED:
1175
		DPRINTF("stop: detaching ...\n");
1176
		umb_packet_service(sc, 0);
1177
		if (!force)
1178
			break;
1179
		/*FALLTHROUGH*/
1180
	case UMB_S_SIMREADY:
1181
	case UMB_S_RADIO:
1182
		DPRINTF("stop: turning radio off ...\n");
1183
		umb_radio(sc, 0);
1184
		if (!force)
1185
			break;
1186
		/*FALLTHROUGH*/
1187
	case UMB_S_CID:
1188
	case UMB_S_OPEN:
1189
	case UMB_S_DOWN:
1190
		/* Do not close the device */
1191
		DPRINTF("stop: reached state DOWN\n");
1192
		break;
1193
	}
1194
	if (force)
1195
		sc->sc_state = UMB_S_OPEN;
1196
1197
	if (sc->sc_state > UMB_S_OPEN)
1198
		usb_callout_reset(&sc->sc_statechg_timer,
1199
		    UMB_STATE_CHANGE_TIMEOUT * hz, umb_statechg_timeout, sc);
1200
	else
1201
		usb_callout_stop(&sc->sc_statechg_timer);
1202
}
1203
1204
static void
1205
umb_get_response_task(struct usb_proc_msg *msg)
1206
{
1207
	struct umb_task *task = (struct umb_task *)msg;
1208
	struct umb_softc *sc = task->sc;
1209
	int	 len;
1210
1211
	DPRINTF("%s()\n", __func__);
1212
	/*
1213
	 * Function is required to send on RESPONSE_AVAILABLE notification for
1214
	 * each encapsulated response that is to be processed by the host.
1215
	 * But of course, we can receive multiple notifications before the
1216
	 * response task is run.
1217
	 */
1218
	while (sc->sc_nresp > 0) {
1219
		--sc->sc_nresp;
1220
		len = sc->sc_ctrl_len;
1221
		if (umb_get_encap_response(sc, sc->sc_resp_buf, &len))
1222
			umb_decode_response(sc, sc->sc_resp_buf, len);
1223
	}
1224
}
1225
1226
static void
1227
umb_decode_response(struct umb_softc *sc, void *response, int len)
1228
{
1229
	struct mbim_msghdr *hdr = response;
1230
	struct mbim_fragmented_msg_hdr *fraghdr;
1231
	uint32_t type;
1232
1233
	DPRINTFN(3, "got response: len %d\n", len);
1234
	DDUMPN(4, response, len);
1235
1236
	if (len < sizeof (*hdr) || le32toh(hdr->len) != len) {
1237
		/*
1238
		 * We should probably cancel a transaction, but since the
1239
		 * message is too short, we cannot decode the transaction
1240
		 * id (tid) and hence don't know, whom to cancel. Must wait
1241
		 * for the timeout.
1242
		 */
1243
		DPRINTF("received short response (len %d)\n",
1244
		    len);
1245
		return;
1246
	}
1247
1248
	/*
1249
	 * XXX FIXME: if message is fragmented, store it until last frag
1250
	 *	is received and then re-assemble all fragments.
1251
	 */
1252
	type = le32toh(hdr->type);
1253
	switch (type) {
1254
	case MBIM_INDICATE_STATUS_MSG:
1255
	case MBIM_COMMAND_DONE:
1256
		fraghdr = response;
1257
		if (le32toh(fraghdr->frag.nfrag) != 1) {
1258
			DPRINTF("discarding fragmented messages\n");
1259
			return;
1260
		}
1261
		break;
1262
	default:
1263
		break;
1264
	}
1265
1266
	DPRINTF("<- rcv %s (tid %u)\n", umb_request2str(type),
1267
	    le32toh(hdr->tid));
1268
	switch (type) {
1269
	case MBIM_FUNCTION_ERROR_MSG:
1270
	case MBIM_HOST_ERROR_MSG:
1271
	{
1272
		struct mbim_f2h_hosterr *e;
1273
		int	 err;
1274
1275
		if (len >= sizeof (*e)) {
1276
			e = response;
1277
			err = le32toh(e->err);
1278
1279
			DPRINTF("%s message, error %s (tid %u)\n",
1280
			    umb_request2str(type),
1281
			    umb_error2str(err), le32toh(hdr->tid));
1282
			if (err == MBIM_ERROR_NOT_OPENED)
1283
				umb_newstate(sc, UMB_S_DOWN, 0);
1284
		}
1285
		break;
1286
	}
1287
	case MBIM_INDICATE_STATUS_MSG:
1288
		umb_handle_indicate_status_msg(sc, response, len);
1289
		break;
1290
	case MBIM_OPEN_DONE:
1291
		umb_handle_opendone_msg(sc, response, len);
1292
		break;
1293
	case MBIM_CLOSE_DONE:
1294
		umb_handle_closedone_msg(sc, response, len);
1295
		break;
1296
	case MBIM_COMMAND_DONE:
1297
		umb_command_done(sc, response, len);
1298
		break;
1299
	default:
1300
		DPRINTF("discard message %s\n",
1301
		    umb_request2str(type));
1302
		break;
1303
	}
1304
}
1305
1306
static void
1307
umb_handle_indicate_status_msg(struct umb_softc *sc, void *data, int len)
1308
{
1309
	struct mbim_f2h_indicate_status *m = data;
1310
	uint32_t infolen;
1311
	uint32_t cid;
1312
1313
	if (len < sizeof (*m)) {
1314
		DPRINTF("discard short %s message\n",
1315
		    umb_request2str(le32toh(m->hdr.type)));
1316
		return;
1317
	}
1318
	if (memcmp(m->devid, umb_uuid_basic_connect, sizeof (m->devid))) {
1319
		DPRINTF("discard %s message for other UUID '%s'\n",
1320
		    umb_request2str(le32toh(m->hdr.type)),
1321
		    umb_uuid2str(m->devid));
1322
		return;
1323
	}
1324
	infolen = le32toh(m->infolen);
1325
	if (len < sizeof (*m) + infolen) {
1326
		DPRINTF("discard truncated %s message (want %d, got %d)\n",
1327
		    umb_request2str(le32toh(m->hdr.type)),
1328
		    (int)sizeof (*m) + infolen, len);
1329
		return;
1330
	}
1331
1332
	cid = le32toh(m->cid);
1333
	DPRINTF("indicate %s status\n", umb_cid2str(cid));
1334
	umb_decode_cid(sc, cid, m->info, infolen);
1335
}
1336
1337
static void
1338
umb_handle_opendone_msg(struct umb_softc *sc, void *data, int len)
1339
{
1340
	struct mbim_f2h_openclosedone *resp = data;
1341
	struct ifnet *ifp = GET_IFP(sc);
1342
	uint32_t status;
1343
1344
	status = le32toh(resp->status);
1345
	if (status == MBIM_STATUS_SUCCESS) {
1346
		if (sc->sc_maxsessions == 0) {
1347
			umb_cmd(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_QRY, NULL,
1348
			    0);
1349
			umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_QRY, NULL, 0);
1350
			umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY,
1351
			    NULL, 0);
1352
		}
1353
		umb_newstate(sc, UMB_S_OPEN, UMB_NS_DONT_DROP);
1354
	} else if (ifp->if_flags & IFF_DEBUG)
1355
		log(LOG_ERR, "%s: open error: %s\n", DEVNAM(sc),
1356
		    umb_status2str(status));
1357
	return;
1358
}
1359
1360
static void
1361
umb_handle_closedone_msg(struct umb_softc *sc, void *data, int len)
1362
{
1363
	struct mbim_f2h_openclosedone *resp = data;
1364
	uint32_t status;
1365
1366
	status = le32toh(resp->status);
1367
	if (status == MBIM_STATUS_SUCCESS)
1368
		umb_newstate(sc, UMB_S_DOWN, 0);
1369
	else
1370
		DPRINTF("close error: %s\n",
1371
		    umb_status2str(status));
1372
	return;
1373
}
1374
1375
static inline void
1376
umb_getinfobuf(char *in, int inlen, uint32_t offs, uint32_t sz,
1377
    void *out, size_t outlen)
1378
{
1379
	offs = le32toh(offs);
1380
	sz = le32toh(sz);
1381
	if (inlen >= offs + sz) {
1382
		memset(out, 0, outlen);
1383
		memcpy(out, in + offs, MIN(sz, outlen));
1384
	}
1385
}
1386
1387
static inline int
1388
umb_padding(void *data, int len, size_t sz)
1389
{
1390
	char *p = data;
1391
	int np = 0;
1392
1393
	while (len < sz && (len % 4) != 0) {
1394
		*p++ = '\0';
1395
		len++;
1396
		np++;
1397
	}
1398
	return np;
1399
}
1400
1401
static inline int
1402
umb_addstr(void *buf, size_t bufsz, int *offs, void *str, int slen,
1403
    uint32_t *offsmember, uint32_t *sizemember)
1404
{
1405
	if (*offs + slen > bufsz)
1406
		return 0;
1407
1408
	*sizemember = htole32((uint32_t)slen);
1409
	if (slen && str) {
1410
		*offsmember = htole32((uint32_t)*offs);
1411
		memcpy((char *)buf + *offs, str, slen);
1412
		*offs += slen;
1413
		*offs += umb_padding(buf, *offs, bufsz);
1414
	} else
1415
		*offsmember = htole32(0);
1416
	return 1;
1417
}
1418
1419
static void
1420
umb_in_len2mask(struct in_addr *mask, int len)
1421
{
1422
	int i;
1423
	u_char *p;
1424
1425
	p = (u_char *)mask;
1426
	memset(mask, 0, sizeof (*mask));
1427
	for (i = 0; i < len / 8; i++)
1428
		p[i] = 0xff;
1429
	if (len % 8)
1430
		p[i] = (0xff00 >> (len % 8)) & 0xff;
1431
}
1432
1433
static int
1434
umb_decode_register_state(struct umb_softc *sc, void *data, int len)
1435
{
1436
	struct mbim_cid_registration_state_info *rs = data;
1437
	struct ifnet *ifp = GET_IFP(sc);
1438
1439
	if (len < sizeof (*rs))
1440
		return 0;
1441
	sc->sc_info.nwerror = le32toh(rs->nwerror);
1442
	sc->sc_info.regstate = le32toh(rs->regstate);
1443
	sc->sc_info.regmode = le32toh(rs->regmode);
1444
	sc->sc_info.cellclass = le32toh(rs->curcellclass);
1445
1446
	/* XXX should we remember the provider_id? */
1447
	umb_getinfobuf(data, len, rs->provname_offs, rs->provname_size,
1448
	    sc->sc_info.provider, sizeof (sc->sc_info.provider));
1449
	umb_getinfobuf(data, len, rs->roamingtxt_offs, rs->roamingtxt_size,
1450
	    sc->sc_info.roamingtxt, sizeof (sc->sc_info.roamingtxt));
1451
1452
	DPRINTFN(2, "%s, availclass 0x%x, class 0x%x, regmode %d\n",
1453
	    umb_regstate(sc->sc_info.regstate),
1454
	    le32toh(rs->availclasses), sc->sc_info.cellclass,
1455
	    sc->sc_info.regmode);
1456
1457
	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING &&
1458
	    !sc->sc_roaming &&
1459
	    sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED) {
1460
		if (ifp->if_flags & IFF_DEBUG)
1461
			log(LOG_INFO,
1462
			    "%s: disconnecting from roaming network\n",
1463
			    DEVNAM(sc));
1464
		umb_disconnect(sc);
1465
	}
1466
	return 1;
1467
}
1468
1469
static int
1470
umb_decode_devices_caps(struct umb_softc *sc, void *data, int len)
1471
{
1472
	struct mbim_cid_device_caps *dc = data;
1473
1474
	if (len < sizeof (*dc))
1475
		return 0;
1476
	sc->sc_maxsessions = le32toh(dc->max_sessions);
1477
	sc->sc_info.supportedclasses = le32toh(dc->dataclass);
1478
	umb_getinfobuf(data, len, dc->devid_offs, dc->devid_size,
1479
	    sc->sc_info.devid, sizeof (sc->sc_info.devid));
1480
	umb_getinfobuf(data, len, dc->fwinfo_offs, dc->fwinfo_size,
1481
	    sc->sc_info.fwinfo, sizeof (sc->sc_info.fwinfo));
1482
	umb_getinfobuf(data, len, dc->hwinfo_offs, dc->hwinfo_size,
1483
	    sc->sc_info.hwinfo, sizeof (sc->sc_info.hwinfo));
1484
	DPRINTFN(2, "max sessions %d, supported classes 0x%x\n",
1485
	    sc->sc_maxsessions, sc->sc_info.supportedclasses);
1486
	return 1;
1487
}
1488
1489
static int
1490
umb_decode_subscriber_status(struct umb_softc *sc, void *data, int len)
1491
{
1492
	struct mbim_cid_subscriber_ready_info *si = data;
1493
	struct ifnet *ifp = GET_IFP(sc);
1494
	int	npn;
1495
1496
	if (len < sizeof (*si))
1497
		return 0;
1498
	sc->sc_info.sim_state = le32toh(si->ready);
1499
1500
	umb_getinfobuf(data, len, si->sid_offs, si->sid_size,
1501
	    sc->sc_info.sid, sizeof (sc->sc_info.sid));
1502
	umb_getinfobuf(data, len, si->icc_offs, si->icc_size,
1503
	    sc->sc_info.iccid, sizeof (sc->sc_info.iccid));
1504
1505
	npn = le32toh(si->no_pn);
1506
	if (npn > 0)
1507
		umb_getinfobuf(data, len, si->pn[0].offs, si->pn[0].size,
1508
		    sc->sc_info.pn, sizeof (sc->sc_info.pn));
1509
	else
1510
		memset(sc->sc_info.pn, 0, sizeof (sc->sc_info.pn));
1511
1512
	if (sc->sc_info.sim_state == MBIM_SIMSTATE_LOCKED)
1513
		sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1514
	if (ifp->if_flags & IFF_DEBUG)
1515
		log(LOG_INFO, "%s: SIM %s\n", DEVNAM(sc),
1516
		    umb_simstate(sc->sc_info.sim_state));
1517
	if (sc->sc_info.sim_state == MBIM_SIMSTATE_INITIALIZED)
1518
		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_DROP);
1519
	return 1;
1520
}
1521
1522
static int
1523
umb_decode_radio_state(struct umb_softc *sc, void *data, int len)
1524
{
1525
	struct mbim_cid_radio_state_info *rs = data;
1526
	struct ifnet *ifp = GET_IFP(sc);
1527
1528
	if (len < sizeof (*rs))
1529
		return 0;
1530
1531
	sc->sc_info.hw_radio_on =
1532
	    (le32toh(rs->hw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1533
	sc->sc_info.sw_radio_on =
1534
	    (le32toh(rs->sw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1535
	if (!sc->sc_info.hw_radio_on) {
1536
		device_printf(sc->sc_dev, "radio is disabled by hardware switch\n");
1537
		/*
1538
		 * XXX do we need a time to poll the state of the rfkill switch
1539
		 *	or will the device send an unsolicited notification
1540
		 *	in case the state changes?
1541
		 */
1542
		umb_newstate(sc, UMB_S_OPEN, 0);
1543
	} else if (!sc->sc_info.sw_radio_on) {
1544
		if (ifp->if_flags & IFF_DEBUG)
1545
			log(LOG_INFO, "%s: radio is off\n", DEVNAM(sc));
1546
		umb_newstate(sc, UMB_S_OPEN, 0);
1547
	} else
1548
		umb_newstate(sc, UMB_S_RADIO, UMB_NS_DONT_DROP);
1549
	return 1;
1550
}
1551
1552
static int
1553
umb_decode_pin(struct umb_softc *sc, void *data, int len)
1554
{
1555
	struct mbim_cid_pin_info *pi = data;
1556
	struct ifnet *ifp = GET_IFP(sc);
1557
	uint32_t	attempts_left;
1558
1559
	if (len < sizeof (*pi))
1560
		return 0;
1561
1562
	attempts_left = le32toh(pi->remaining_attempts);
1563
	if (attempts_left != 0xffffffff)
1564
		sc->sc_info.pin_attempts_left = attempts_left;
1565
1566
	switch (le32toh(pi->state)) {
1567
	case MBIM_PIN_STATE_UNLOCKED:
1568
		sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1569
		break;
1570
	case MBIM_PIN_STATE_LOCKED:
1571
		switch (le32toh(pi->type)) {
1572
		case MBIM_PIN_TYPE_PIN1:
1573
			sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1574
			break;
1575
		case MBIM_PIN_TYPE_PUK1:
1576
			sc->sc_info.pin_state = UMB_PUK_REQUIRED;
1577
			break;
1578
		case MBIM_PIN_TYPE_PIN2:
1579
		case MBIM_PIN_TYPE_PUK2:
1580
			/* Assume that PIN1 was accepted */
1581
			sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1582
			break;
1583
		}
1584
		break;
1585
	}
1586
	if (ifp->if_flags & IFF_DEBUG)
1587
		log(LOG_INFO, "%s: %s state %s (%d attempts left)\n",
1588
		    DEVNAM(sc), umb_pin_type(le32toh(pi->type)),
1589
		    (le32toh(pi->state) == MBIM_PIN_STATE_UNLOCKED) ?
1590
			"unlocked" : "locked",
1591
		    le32toh(pi->remaining_attempts));
1592
1593
	/*
1594
	 * In case the PIN was set after IFF_UP, retrigger the state machine
1595
	 */
1596
	umb_add_task(sc, umb_state_task,
1597
			&sc->sc_proc_state_task[0].hdr,
1598
			&sc->sc_proc_state_task[1].hdr, 0);
1599
	return 1;
1600
}
1601
1602
static int
1603
umb_decode_packet_service(struct umb_softc *sc, void *data, int len)
1604
{
1605
	struct mbim_cid_packet_service_info *psi = data;
1606
	int	 state, highestclass;
1607
	uint64_t up_speed, down_speed;
1608
	struct ifnet *ifp = GET_IFP(sc);
1609
1610
	if (len < sizeof (*psi))
1611
		return 0;
1612
1613
	sc->sc_info.nwerror = le32toh(psi->nwerror);
1614
	state = le32toh(psi->state);
1615
	highestclass = le32toh(psi->highest_dataclass);
1616
	up_speed = le64toh(psi->uplink_speed);
1617
	down_speed = le64toh(psi->downlink_speed);
1618
	if (sc->sc_info.packetstate  != state ||
1619
	    sc->sc_info.uplink_speed != up_speed ||
1620
	    sc->sc_info.downlink_speed != down_speed) {
1621
		if (ifp->if_flags & IFF_DEBUG) {
1622
			log(LOG_INFO, "%s: packet service ", DEVNAM(sc));
1623
			if (sc->sc_info.packetstate  != state)
1624
				log(LOG_INFO, "changed from %s to ",
1625
				    umb_packet_state(sc->sc_info.packetstate));
1626
			log(LOG_INFO, "%s, class %s, speed: %" PRIu64 " up / %" PRIu64 " down\n",
1627
			    umb_packet_state(state),
1628
			    umb_dataclass(highestclass), up_speed, down_speed);
1629
		}
1630
	}
1631
	sc->sc_info.packetstate = state;
1632
	sc->sc_info.highestclass = highestclass;
1633
	sc->sc_info.uplink_speed = up_speed;
1634
	sc->sc_info.downlink_speed = down_speed;
1635
1636
	if (sc->sc_info.regmode == MBIM_REGMODE_AUTOMATIC) {
1637
		/*
1638
		 * For devices using automatic registration mode, just proceed,
1639
		 * once registration has completed.
1640
		 */
1641
		if (ifp->if_flags & IFF_UP) {
1642
			switch (sc->sc_info.regstate) {
1643
			case MBIM_REGSTATE_HOME:
1644
			case MBIM_REGSTATE_ROAMING:
1645
			case MBIM_REGSTATE_PARTNER:
1646
				umb_newstate(sc, UMB_S_ATTACHED,
1647
				    UMB_NS_DONT_DROP);
1648
				break;
1649
			default:
1650
				break;
1651
			}
1652
		} else
1653
			umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1654
	} else switch (sc->sc_info.packetstate) {
1655
	case MBIM_PKTSERVICE_STATE_ATTACHED:
1656
		umb_newstate(sc, UMB_S_ATTACHED, UMB_NS_DONT_DROP);
1657
		break;
1658
	case MBIM_PKTSERVICE_STATE_DETACHED:
1659
		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1660
		break;
1661
	}
1662
	return 1;
1663
}
1664
1665
static int
1666
umb_decode_signal_state(struct umb_softc *sc, void *data, int len)
1667
{
1668
	struct mbim_cid_signal_state *ss = data;
1669
	struct ifnet *ifp = GET_IFP(sc);
1670
	int	 rssi;
1671
1672
	if (len < sizeof (*ss))
1673
		return 0;
1674
1675
	if (le32toh(ss->rssi) == 99)
1676
		rssi = UMB_VALUE_UNKNOWN;
1677
	else {
1678
		rssi = -113 + 2 * le32toh(ss->rssi);
1679
		if ((ifp->if_flags & IFF_DEBUG) && sc->sc_info.rssi != rssi &&
1680
		    sc->sc_state >= UMB_S_CONNECTED)
1681
			log(LOG_INFO, "%s: rssi %d dBm\n", DEVNAM(sc), rssi);
1682
	}
1683
	sc->sc_info.rssi = rssi;
1684
	sc->sc_info.ber = le32toh(ss->err_rate);
1685
	if (sc->sc_info.ber == -99)
1686
		sc->sc_info.ber = UMB_VALUE_UNKNOWN;
1687
	return 1;
1688
}
1689
1690
static int
1691
umb_decode_connect_info(struct umb_softc *sc, void *data, int len)
1692
{
1693
	struct mbim_cid_connect_info *ci = data;
1694
	struct ifnet *ifp = GET_IFP(sc);
1695
	int	 act;
1696
1697
	if (len < sizeof (*ci))
1698
		return 0;
1699
1700
	if (le32toh(ci->sessionid) != umb_session_id) {
1701
		DPRINTF("discard connection info for session %u\n",
1702
		    le32toh(ci->sessionid));
1703
		return 1;
1704
	}
1705
	if (memcmp(ci->context, umb_uuid_context_internet,
1706
	    sizeof (ci->context))) {
1707
		DPRINTF("discard connection info for other context\n");
1708
		return 1;
1709
	}
1710
	act = le32toh(ci->activation);
1711
	if (sc->sc_info.activation != act) {
1712
		if (ifp->if_flags & IFF_DEBUG)
1713
			log(LOG_INFO, "%s: connection %s\n", DEVNAM(sc),
1714
			    umb_activation(act));
1715
		if ((ifp->if_flags & IFF_DEBUG) &&
1716
		    le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_DEFAULT &&
1717
		    le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_IPV4)
1718
			log(LOG_DEBUG, "%s: got iptype %d connection\n",
1719
			    DEVNAM(sc), le32toh(ci->iptype));
1720
1721
		sc->sc_info.activation = act;
1722
		sc->sc_info.nwerror = le32toh(ci->nwerror);
1723
1724
		if (sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED)
1725
			umb_newstate(sc, UMB_S_CONNECTED, UMB_NS_DONT_DROP);
1726
		else if (sc->sc_info.activation ==
1727
		    MBIM_ACTIVATION_STATE_DEACTIVATED)
1728
			umb_newstate(sc, UMB_S_ATTACHED, 0);
1729
		/* else: other states are purely transitional */
1730
	}
1731
	return 1;
1732
}
1733
1734
static int
1735
umb_add_inet_config(struct umb_softc *sc, struct in_addr ip, u_int prefixlen,
1736
    struct in_addr gw)
1737
{
1738
	struct ifnet *ifp = GET_IFP(sc);
1739
	struct in_aliasreq ifra;
1740
	struct sockaddr_in *sin;
1741
	int	 rv;
1742
1743
	memset(&ifra, 0, sizeof (ifra));
1744
	sin = (struct sockaddr_in *)&ifra.ifra_addr;
1745
	sin->sin_family = AF_INET;
1746
	sin->sin_len = sizeof (*sin);
1747
	sin->sin_addr = ip;
1748
1749
	sin = (struct sockaddr_in *)&ifra.ifra_dstaddr;
1750
	sin->sin_family = AF_INET;
1751
	sin->sin_len = sizeof (*sin);
1752
	sin->sin_addr = gw;
1753
1754
	sin = (struct sockaddr_in *)&ifra.ifra_mask;
1755
	sin->sin_family = AF_INET;
1756
	sin->sin_len = sizeof (*sin);
1757
	umb_in_len2mask(&sin->sin_addr, prefixlen);
1758
1759
	mtx_unlock(&sc->sc_mutex);
1760
	CURVNET_SET_QUIET(vnet0);
1761
	rv = in_control(NULL, SIOCAIFADDR, (caddr_t)&ifra, ifp, curthread);
1762
	CURVNET_RESTORE();
1763
	mtx_lock(&sc->sc_mutex);
1764
	if (rv != 0) {
1765
		device_printf(sc->sc_dev, "unable to set IPv4 address, error %d\n",
1766
		    rv);
1767
		return rv;
1768
	}
1769
1770
	if (ifp->if_flags & IFF_DEBUG)
1771
		log(LOG_INFO, "%s: IPv4 addr %s, mask %s, "
1772
		    "gateway %s\n", DEVNAM(sc),
1773
		    umb_ntop(sintosa(&ifra.ifra_addr)),
1774
		    umb_ntop(sintosa(&ifra.ifra_mask)),
1775
		    umb_ntop(sintosa(&ifra.ifra_dstaddr)));
1776
1777
	return 0;
1778
}
1779
1780
static int
1781
umb_decode_ip_configuration(struct umb_softc *sc, void *data, int len)
1782
{
1783
	struct mbim_cid_ip_configuration_info *ic = data;
1784
	struct ifnet *ifp = GET_IFP(sc);
1785
	uint32_t avail_v4;
1786
	uint32_t val;
1787
	int	 n, i;
1788
	int	 off;
1789
	struct mbim_cid_ipv4_element ipv4elem;
1790
	struct in_addr addr, gw;
1791
	int	 state = -1;
1792
	int	 rv;
1793
1794
	if (len < sizeof (*ic))
1795
		return 0;
1796
	if (le32toh(ic->sessionid) != umb_session_id) {
1797
		DPRINTF("ignore IP configuration for session id %d\n",
1798
		    le32toh(ic->sessionid));
1799
		return 0;
1800
	}
1801
1802
	/*
1803
	 * IPv4 configuration
1804
	 */
1805
	avail_v4 = le32toh(ic->ipv4_available);
1806
	if ((avail_v4 & (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) ==
1807
	    (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) {
1808
		n = le32toh(ic->ipv4_naddr);
1809
		off = le32toh(ic->ipv4_addroffs);
1810
1811
		if (n == 0 || off + sizeof (ipv4elem) > len)
1812
			goto tryv6;
1813
		if (n != 1 && ifp->if_flags & IFF_DEBUG)
1814
			log(LOG_INFO, "%s: more than one IPv4 addr: %d\n",
1815
			    DEVNAM(sc), n);
1816
1817
		/* Only pick the first one */
1818
		memcpy(&ipv4elem, (char *)data + off, sizeof (ipv4elem));
1819
		ipv4elem.prefixlen = le32toh(ipv4elem.prefixlen);
1820
		addr.s_addr = ipv4elem.addr;
1821
1822
		off = le32toh(ic->ipv4_gwoffs);
1823
		if (off + sizeof (gw) > len)
1824
			goto done;
1825
		memcpy(&gw, (char *)data + off, sizeof (gw));
1826
1827
		rv = umb_add_inet_config(sc, addr, ipv4elem.prefixlen, gw);
1828
		if (rv == 0)
1829
			state = UMB_S_UP;
1830
	}
1831
1832
	memset(sc->sc_info.ipv4dns, 0, sizeof (sc->sc_info.ipv4dns));
1833
	if (avail_v4 & MBIM_IPCONF_HAS_DNSINFO) {
1834
		n = le32toh(ic->ipv4_ndnssrv);
1835
		off = le32toh(ic->ipv4_dnssrvoffs);
1836
		i = 0;
1837
		while (n-- > 0) {
1838
			if (off + sizeof (addr) > len)
1839
				break;
1840
			memcpy(&addr, (char *)data + off, sizeof(addr));
1841
			if (i < UMB_MAX_DNSSRV)
1842
				sc->sc_info.ipv4dns[i++] = addr;
1843
			off += sizeof(addr);
1844
		}
1845
	}
1846
1847
	if ((avail_v4 & MBIM_IPCONF_HAS_MTUINFO)) {
1848
		val = le32toh(ic->ipv4_mtu);
1849
		if (ifp->if_mtu != val && val <= sc->sc_maxpktlen) {
1850
			ifp->if_mtu = val;
1851
			if (ifp->if_mtu > val)
1852
				ifp->if_mtu = val;
1853
			if (ifp->if_flags & IFF_DEBUG)
1854
				log(LOG_INFO, "%s: MTU %d\n", DEVNAM(sc), val);
1855
		}
1856
	}
1857
1858
	avail_v4 = le32toh(ic->ipv6_available);
1859
	if ((ifp->if_flags & IFF_DEBUG) && avail_v4 & MBIM_IPCONF_HAS_ADDRINFO) {
1860
		/* XXX FIXME: IPv6 configuration missing */
1861
		log(LOG_INFO, "%s: ignoring IPv6 configuration\n", DEVNAM(sc));
1862
	}
1863
	if (state != -1)
1864
		umb_newstate(sc, state, 0);
1865
1866
tryv6:
1867
done:
1868
	return 1;
1869
}
1870
1871
static void
1872
umb_rx(struct umb_softc *sc)
1873
{
1874
	mtx_assert(&sc->sc_mutex, MA_OWNED);
1875
1876
	usbd_transfer_start(sc->sc_xfer[UMB_BULK_RX]);
1877
}
1878
1879
static void
1880
umb_rxeof(struct usb_xfer *xfer, usb_error_t status)
1881
{
1882
	struct umb_softc *sc = usbd_xfer_softc(xfer);
1883
	struct ifnet *ifp = GET_IFP(sc);
1884
	int actlen;
1885
	int aframes;
1886
	int i;
1887
1888
	DPRINTF("%s(%u): state=%u\n", __func__, status, USB_GET_STATE(xfer));
1889
1890
	mtx_assert(&sc->sc_mutex, MA_OWNED);
1891
1892
	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
1893
1894
	switch (USB_GET_STATE(xfer)) {
1895
	case USB_ST_TRANSFERRED:
1896
		DPRINTF("received %u bytes in %u frames\n", actlen, aframes);
1897
1898
		if (actlen == 0) {
1899
			if (sc->sc_rx_nerr >= 4)
1900
				/* throttle transfers */
1901
				usbd_xfer_set_interval(xfer, 500);
1902
			else
1903
				sc->sc_rx_nerr++;
1904
		}
1905
		else {
1906
			/* disable throttling */
1907
			usbd_xfer_set_interval(xfer, 0);
1908
			sc->sc_rx_nerr = 0;
1909
		}
1910
1911
		for(i = 0; i < aframes; i++) {
1912
			umb_decap(sc, xfer, i);
1913
		}
1914
1915
		/* fall through */
1916
	case USB_ST_SETUP:
1917
		usbd_xfer_set_frame_data(xfer, 0, sc->sc_rx_buf,
1918
				sc->sc_rx_bufsz);
1919
		usbd_xfer_set_frames(xfer, 1);
1920
		usbd_transfer_submit(xfer);
1921
1922
		umb_rxflush(sc);
1923
		break;
1924
	default:
1925
		DPRINTF("rx error: %s\n", usbd_errstr(status));
1926
1927
		/* disable throttling */
1928
		usbd_xfer_set_interval(xfer, 0);
1929
1930
		if (status != USB_ERR_CANCELLED) {
1931
			/* try to clear stall first */
1932
			usbd_xfer_set_stall(xfer);
1933
			usbd_xfer_set_frames(xfer, 0);
1934
			usbd_transfer_submit(xfer);
1935
			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1936
		}
1937
		else if (++sc->sc_rx_nerr > 100) {
1938
			log(LOG_ERR, "%s: too many rx errors, disabling\n",
1939
			    DEVNAM(sc));
1940
			umb_deactivate(sc->sc_dev);
1941
		}
1942
		break;
1943
	}
1944
}
1945
1946
static void
1947
umb_rxflush(struct umb_softc *sc)
1948
{
1949
	struct ifnet *ifp = GET_IFP(sc);
1950
	struct mbuf *m;
1951
1952
	mtx_assert(&sc->sc_mutex, MA_OWNED);
1953
1954
	for (;;) {
1955
		_IF_DEQUEUE(&sc->sc_rx_queue, m);
1956
		if (m == NULL)
1957
			break;
1958
1959
		/*
1960
		 * The USB xfer has been resubmitted so its safe to unlock now.
1961
		 */
1962
		mtx_unlock(&sc->sc_mutex);
1963
		CURVNET_SET_QUIET(vnet0);
1964
		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1965
			ifp->if_input(ifp, m);
1966
		else
1967
			m_freem(m);
1968
		CURVNET_RESTORE();
1969
		mtx_lock(&sc->sc_mutex);
1970
	}
1971
}
1972
1973
static int
1974
umb_encap(struct umb_softc *sc, struct mbuf *m, struct usb_xfer *xfer)
1975
{
1976
	struct ncm_header16 *hdr;
1977
	struct ncm_pointer16 *ptr;
1978
	int	 len;
1979
1980
	KASSERT(sc->sc_tx_m == NULL,
1981
			("Assertion failed in umb_encap()"));
1982
1983
	/* All size constraints have been validated by the caller! */
1984
	hdr = (struct ncm_header16 *)sc->sc_tx_buf;
1985
	ptr = (struct ncm_pointer16 *)(hdr + 1);
1986
1987
	USETDW(hdr->dwSignature, NCM_HDR16_SIG);
1988
	USETW(hdr->wHeaderLength, sizeof (*hdr));
1989
	USETW(hdr->wSequence, sc->sc_tx_seq);
1990
	sc->sc_tx_seq++;
1991
	USETW(hdr->wNdpIndex, sizeof (*hdr));
1992
1993
	len = m->m_pkthdr.len;
1994
	USETDW(ptr->dwSignature, MBIM_NCM_NTH16_SIG(umb_session_id));
1995
	USETW(ptr->wLength, sizeof (*ptr));
1996
	USETW(ptr->wNextNdpIndex, 0);
1997
	USETW(ptr->dgram[0].wDatagramIndex, MBIM_HDR16_LEN);
1998
	USETW(ptr->dgram[0].wDatagramLen, len);
1999
	USETW(ptr->dgram[1].wDatagramIndex, 0);
2000
	USETW(ptr->dgram[1].wDatagramLen, 0);
2001
2002
	KASSERT(len + MBIM_HDR16_LEN <= sc->sc_tx_bufsz,
2003
			("Assertion failed in umb_encap()"));
2004
	m_copydata(m, 0, len, (char *)(ptr + 1));
2005
	sc->sc_tx_m = m;
2006
	len += MBIM_HDR16_LEN;
2007
	USETW(hdr->wBlockLength, len);
2008
2009
	usbd_xfer_set_frame_data(xfer, 0, sc->sc_tx_buf, len);
2010
	usbd_xfer_set_interval(xfer, 0);
2011
	usbd_xfer_set_frames(xfer, 1);
2012
2013
	DPRINTFN(3, "%s: encap %d bytes\n", DEVNAM(sc), len);
2014
	DDUMPN(5, sc->sc_tx_buf, len);
2015
	return 0;
2016
}
2017
2018
static void
2019
umb_txeof(struct usb_xfer *xfer, usb_error_t status)
2020
{
2021
	struct umb_softc *sc = usbd_xfer_softc(xfer);
2022
	struct ifnet *ifp = GET_IFP(sc);
2023
	struct mbuf *m;
2024
2025
	DPRINTF("%s(%u) state=%u\n", __func__, status, USB_GET_STATE(xfer));
2026
2027
	mtx_assert(&sc->sc_mutex, MA_OWNED);
2028
2029
	switch (USB_GET_STATE(xfer)) {
2030
	case USB_ST_TRANSFERRED:
2031
		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2032
		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2033
2034
		umb_txflush(sc);
2035
2036
		/* fall through */
2037
	case USB_ST_SETUP:
2038
tr_setup:
2039
		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
2040
			break;
2041
2042
		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
2043
		if (m == NULL)
2044
			break;
2045
2046
		if (umb_encap(sc, m, xfer)) {
2047
			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2048
			umb_txflush(sc);
2049
			break;
2050
		}
2051
2052
		BPF_MTAP(ifp, m);
2053
2054
		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
2055
		usbd_transfer_submit(xfer);
2056
2057
		break;
2058
2059
	default:
2060
		umb_txflush(sc);
2061
2062
		/* count output errors */
2063
		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2064
		DPRINTF("tx error: %s\n",
2065
				usbd_errstr(status));
2066
2067
		if (status != USB_ERR_CANCELLED) {
2068
			/* try to clear stall first */
2069
			usbd_xfer_set_stall(xfer);
2070
			goto tr_setup;
2071
		}
2072
		break;
2073
	}
2074
}
2075
2076
static void
2077
umb_txflush(struct umb_softc *sc)
2078
{
2079
	mtx_assert(&sc->sc_mutex, MA_OWNED);
2080
2081
	if (sc->sc_tx_m != NULL) {
2082
		m_freem(sc->sc_tx_m);
2083
		sc->sc_tx_m = NULL;
2084
	}
2085
}
2086
2087
static void
2088
umb_decap(struct umb_softc *sc, struct usb_xfer *xfer, int frame)
2089
{
2090
	struct ifnet *ifp = GET_IFP(sc);
2091
	char *buf;
2092
	int len;
2093
	char	*dp;
2094
	struct ncm_header16 *hdr16;
2095
	struct ncm_header32 *hdr32;
2096
	struct ncm_pointer16 *ptr16;
2097
	struct ncm_pointer16_dgram *dgram16;
2098
	struct ncm_pointer32_dgram *dgram32;
2099
	uint32_t hsig, psig;
2100
	int	 hlen, blen;
2101
	int	 ptrlen, ptroff, dgentryoff;
2102
	uint32_t doff, dlen;
2103
	struct mbuf *m;
2104
2105
	usbd_xfer_frame_data(xfer, frame, (void **)&buf, &len);
2106
	DPRINTFN(4, "recv %d bytes\n", len);
2107
	DDUMPN(5, buf, len);
2108
	if (len < sizeof (*hdr16))
2109
		goto toosmall;
2110
2111
	hdr16 = (struct ncm_header16 *)buf;
2112
	hsig = UGETDW(hdr16->dwSignature);
2113
	hlen = UGETW(hdr16->wHeaderLength);
2114
	if (len < hlen)
2115
		goto toosmall;
2116
	if (len > sc->sc_rx_bufsz) {
2117
		DPRINTF("packet too large (%d)\n", len);
2118
		goto fail;
2119
	}
2120
	switch (hsig) {
2121
	case NCM_HDR16_SIG:
2122
		blen = UGETW(hdr16->wBlockLength);
2123
		ptroff = UGETW(hdr16->wNdpIndex);
2124
		if (hlen != sizeof (*hdr16)) {
2125
			DPRINTF("%s: bad header len %d for NTH16 (exp %zu)\n",
2126
			    DEVNAM(sc), hlen, sizeof (*hdr16));
2127
			goto fail;
2128
		}
2129
		break;
2130
	case NCM_HDR32_SIG:
2131
		hdr32 = (struct ncm_header32 *)hdr16;
2132
		blen = UGETDW(hdr32->dwBlockLength);
2133
		ptroff = UGETDW(hdr32->dwNdpIndex);
2134
		if (hlen != sizeof (*hdr32)) {
2135
			DPRINTF("%s: bad header len %d for NTH32 (exp %zu)\n",
2136
			    DEVNAM(sc), hlen, sizeof (*hdr32));
2137
			goto fail;
2138
		}
2139
		break;
2140
	default:
2141
		DPRINTF("%s: unsupported NCM header signature (0x%08x)\n",
2142
		    DEVNAM(sc), hsig);
2143
		goto fail;
2144
	}
2145
	if (len < blen) {
2146
		DPRINTF("%s: bad NTB len (%d) for %d bytes of data\n",
2147
		    DEVNAM(sc), blen, len);
2148
		goto fail;
2149
	}
2150
2151
	ptr16 = (struct ncm_pointer16 *)(buf + ptroff);
2152
	psig = UGETDW(ptr16->dwSignature);
2153
	ptrlen = UGETW(ptr16->wLength);
2154
	if (len < ptrlen + ptroff)
2155
		goto toosmall;
2156
	if (!MBIM_NCM_NTH16_ISISG(psig) && !MBIM_NCM_NTH32_ISISG(psig)) {
2157
		DPRINTF("%s: unsupported NCM pointer signature (0x%08x)\n",
2158
		    DEVNAM(sc), psig);
2159
		goto fail;
2160
	}
2161
2162
	switch (hsig) {
2163
	case NCM_HDR16_SIG:
2164
		dgentryoff = offsetof(struct ncm_pointer16, dgram);
2165
		break;
2166
	case NCM_HDR32_SIG:
2167
		dgentryoff = offsetof(struct ncm_pointer32, dgram);
2168
		break;
2169
	default:
2170
		goto fail;
2171
	}
2172
2173
	while (dgentryoff < ptrlen) {
2174
		switch (hsig) {
2175
		case NCM_HDR16_SIG:
2176
			if (ptroff + dgentryoff < sizeof (*dgram16))
2177
				goto done;
2178
			dgram16 = (struct ncm_pointer16_dgram *)
2179
			    (buf + ptroff + dgentryoff);
2180
			dgentryoff += sizeof (*dgram16);
2181
			dlen = UGETW(dgram16->wDatagramLen);
2182
			doff = UGETW(dgram16->wDatagramIndex);
2183
			break;
2184
		case NCM_HDR32_SIG:
2185
			if (ptroff + dgentryoff < sizeof (*dgram32))
2186
				goto done;
2187
			dgram32 = (struct ncm_pointer32_dgram *)
2188
			    (buf + ptroff + dgentryoff);
2189
			dgentryoff += sizeof (*dgram32);
2190
			dlen = UGETDW(dgram32->dwDatagramLen);
2191
			doff = UGETDW(dgram32->dwDatagramIndex);
2192
			break;
2193
		default:
2194
			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2195
			goto done;
2196
		}
2197
2198
		/* Terminating zero entry */
2199
		if (dlen == 0 || doff == 0)
2200
			break;
2201
		if (len < dlen + doff) {
2202
			/* Skip giant datagram but continue processing */
2203
			DPRINTF("%s: datagram too large (%d @ off %d)\n",
2204
			    DEVNAM(sc), dlen, doff);
2205
			continue;
2206
		}
2207
2208
		dp = buf + doff;
2209
		DPRINTFN(3, "%s: decap %d bytes\n", DEVNAM(sc), dlen);
2210
		m = m_devget(dp, dlen, 0, ifp, NULL);
2211
		if (m == NULL) {
2212
			if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2213
			continue;
2214
		}
2215
2216
		/* enqueue for later when the lock can be released */
2217
		_IF_ENQUEUE(&sc->sc_rx_queue, m);
2218
2219
		if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
2220
2221
	}
2222
done:
2223
	sc->sc_rx_nerr = 0;
2224
	return;
2225
toosmall:
2226
	DPRINTF("%s: packet too small (%d)\n", DEVNAM(sc), len);
2227
fail:
2228
	if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2229
}
2230
2231
static usb_error_t
2232
umb_send_encap_command(struct umb_softc *sc, void *data, int len)
2233
{
2234
	usb_device_request_t req;
2235
2236
	if (len > sc->sc_ctrl_len)
2237
		return USB_ERR_INVAL;
2238
2239
	/* XXX FIXME: if (total len > sc->sc_ctrl_len) => must fragment */
2240
	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
2241
	req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
2242
	USETW(req.wValue, 0);
2243
	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2244
	USETW(req.wLength, len);
2245
	mtx_unlock(&sc->sc_mutex);
2246
	DELAY(umb_delay);
2247
	mtx_lock(&sc->sc_mutex);
2248
	return usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, data, 0,
2249
			NULL, umb_xfer_tout);
2250
}
2251
2252
static int
2253
umb_get_encap_response(struct umb_softc *sc, void *buf, int *len)
2254
{
2255
	usb_device_request_t req;
2256
	usb_error_t err;
2257
	uint16_t l = *len;
2258
2259
	req.bmRequestType = UT_READ_CLASS_INTERFACE;
2260
	req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
2261
	USETW(req.wValue, 0);
2262
	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2263
	USETW(req.wLength, l);
2264
	/* XXX FIXME: re-assemble fragments */
2265
2266
	mtx_unlock(&sc->sc_mutex);
2267
	DELAY(umb_delay);
2268
	mtx_lock(&sc->sc_mutex);
2269
	err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, buf,
2270
			USB_SHORT_XFER_OK, &l, umb_xfer_tout);
2271
	if (err == USB_ERR_NORMAL_COMPLETION) {
2272
		*len = l;
2273
		return 1;
2274
	}
2275
	DPRINTF("ctrl recv: %s\n", usbd_errstr(err));
2276
	return 0;
2277
}
2278
2279
static void
2280
umb_ctrl_msg(struct umb_softc *sc, uint32_t req, void *data, int len)
2281
{
2282
	struct ifnet *ifp = GET_IFP(sc);
2283
	uint32_t tid;
2284
	struct mbim_msghdr *hdr = data;
2285
	usb_error_t err;
2286
2287
	if (sc->sc_dying)
2288
		return;
2289
	if (len < sizeof (*hdr))
2290
		return;
2291
	tid = ++sc->sc_tid;
2292
2293
	hdr->type = htole32(req);
2294
	hdr->len = htole32(len);
2295
	hdr->tid = htole32(tid);
2296
2297
#ifdef UMB_DEBUG
2298
	if (umb_debug) {
2299
		const char *op, *str;
2300
		if (req == MBIM_COMMAND_MSG) {
2301
			struct mbim_h2f_cmd *c = data;
2302
			if (le32toh(c->op) == MBIM_CMDOP_SET)
2303
				op = "set";
2304
			else
2305
				op = "qry";
2306
			str = umb_cid2str(le32toh(c->cid));
2307
		} else {
2308
			op = "snd";
2309
			str = umb_request2str(req);
2310
		}
2311
		DPRINTF("-> %s %s (tid %u)\n", op, str, tid);
2312
	}
2313
#endif
2314
	err = umb_send_encap_command(sc, data, len);
2315
	if (err != USB_ERR_NORMAL_COMPLETION) {
2316
		if (ifp->if_flags & IFF_DEBUG)
2317
			log(LOG_ERR, "%s: send %s msg (tid %u) failed: %s\n",
2318
			    DEVNAM(sc), umb_request2str(req), tid,
2319
			    usbd_errstr(err));
2320
2321
		/* will affect other transactions, too */
2322
		usbd_transfer_stop(sc->sc_xfer[UMB_INTR_RX]);
2323
	} else {
2324
		DPRINTFN(2, "sent %s (tid %u)\n",
2325
		    umb_request2str(req), tid);
2326
		DDUMPN(3, data, len);
2327
	}
2328
	return;
2329
}
2330
2331
static void
2332
umb_open(struct umb_softc *sc)
2333
{
2334
	struct mbim_h2f_openmsg msg;
2335
2336
	memset(&msg, 0, sizeof (msg));
2337
	msg.maxlen = htole32(sc->sc_ctrl_len);
2338
	umb_ctrl_msg(sc, MBIM_OPEN_MSG, &msg, sizeof (msg));
2339
	return;
2340
}
2341
2342
static void
2343
umb_close(struct umb_softc *sc)
2344
{
2345
	struct mbim_h2f_closemsg msg;
2346
2347
	memset(&msg, 0, sizeof (msg));
2348
	umb_ctrl_msg(sc, MBIM_CLOSE_MSG, &msg, sizeof (msg));
2349
}
2350
2351
static int
2352
umb_setpin(struct umb_softc *sc, int op, int is_puk, void *pin, int pinlen,
2353
    void *newpin, int newpinlen)
2354
{
2355
	struct mbim_cid_pin cp;
2356
	int	 off;
2357
2358
	if (pinlen == 0)
2359
		return 0;
2360
	if (pinlen < 0 || pinlen > MBIM_PIN_MAXLEN ||
2361
	    newpinlen < 0 || newpinlen > MBIM_PIN_MAXLEN ||
2362
	    op < 0 || op > MBIM_PIN_OP_CHANGE ||
2363
	    (is_puk && op != MBIM_PIN_OP_ENTER))
2364
		return EINVAL;
2365
2366
	memset(&cp, 0, sizeof (cp));
2367
	cp.type = htole32(is_puk ? MBIM_PIN_TYPE_PUK1 : MBIM_PIN_TYPE_PIN1);
2368
2369
	off = offsetof(struct mbim_cid_pin, data);
2370
	if (!umb_addstr(&cp, sizeof (cp), &off, pin, pinlen,
2371
	    &cp.pin_offs, &cp.pin_size))
2372
		return EINVAL;
2373
2374
	cp.op  = htole32(op);
2375
	if (newpinlen) {
2376
		if (!umb_addstr(&cp, sizeof (cp), &off, newpin, newpinlen,
2377
		    &cp.newpin_offs, &cp.newpin_size))
2378
			return EINVAL;
2379
	} else {
2380
		if ((op == MBIM_PIN_OP_CHANGE) || is_puk)
2381
			return EINVAL;
2382
		if (!umb_addstr(&cp, sizeof (cp), &off, NULL, 0,
2383
		    &cp.newpin_offs, &cp.newpin_size))
2384
			return EINVAL;
2385
	}
2386
	mtx_lock(&sc->sc_mutex);
2387
	umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_SET, &cp, off);
2388
	mtx_unlock(&sc->sc_mutex);
2389
	return 0;
2390
}
2391
2392
static void
2393
umb_setdataclass(struct umb_softc *sc)
2394
{
2395
	struct mbim_cid_registration_state rs;
2396
	uint32_t	 classes;
2397
2398
	if (sc->sc_info.supportedclasses == MBIM_DATACLASS_NONE)
2399
		return;
2400
2401
	memset(&rs, 0, sizeof (rs));
2402
	rs.regaction = htole32(MBIM_REGACTION_AUTOMATIC);
2403
	classes = sc->sc_info.supportedclasses;
2404
	if (sc->sc_info.preferredclasses != MBIM_DATACLASS_NONE)
2405
		classes &= sc->sc_info.preferredclasses;
2406
	rs.data_class = htole32(classes);
2407
	mtx_lock(&sc->sc_mutex);
2408
	umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_SET, &rs, sizeof (rs));
2409
	mtx_unlock(&sc->sc_mutex);
2410
}
2411
2412
static void
2413
umb_radio(struct umb_softc *sc, int on)
2414
{
2415
	struct mbim_cid_radio_state s;
2416
2417
	DPRINTF("set radio %s\n", on ? "on" : "off");
2418
	memset(&s, 0, sizeof (s));
2419
	s.state = htole32(on ? MBIM_RADIO_STATE_ON : MBIM_RADIO_STATE_OFF);
2420
	umb_cmd(sc, MBIM_CID_RADIO_STATE, MBIM_CMDOP_SET, &s, sizeof (s));
2421
}
2422
2423
static void
2424
umb_allocate_cid(struct umb_softc *sc)
2425
{
2426
	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2427
	    umb_qmi_alloc_cid, sizeof (umb_qmi_alloc_cid), umb_uuid_qmi_mbim);
2428
}
2429
2430
static void
2431
umb_send_fcc_auth(struct umb_softc *sc)
2432
{
2433
	uint8_t	 fccauth[sizeof (umb_qmi_fcc_auth)];
2434
2435
	if (sc->sc_cid == -1) {
2436
		DPRINTF("missing CID, cannot send FCC auth\n");
2437
		umb_allocate_cid(sc);
2438
		return;
2439
	}
2440
	memcpy(fccauth, umb_qmi_fcc_auth, sizeof (fccauth));
2441
	fccauth[UMB_QMI_CID_OFFS] = sc->sc_cid;
2442
	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2443
	    fccauth, sizeof (fccauth), umb_uuid_qmi_mbim);
2444
}
2445
2446
static void
2447
umb_packet_service(struct umb_softc *sc, int attach)
2448
{
2449
	struct mbim_cid_packet_service	s;
2450
2451
	DPRINTF("%s packet service\n",
2452
	    attach ? "attach" : "detach");
2453
	memset(&s, 0, sizeof (s));
2454
	s.action = htole32(attach ?
2455
	    MBIM_PKTSERVICE_ACTION_ATTACH : MBIM_PKTSERVICE_ACTION_DETACH);
2456
	umb_cmd(sc, MBIM_CID_PACKET_SERVICE, MBIM_CMDOP_SET, &s, sizeof (s));
2457
}
2458
2459
static void
2460
umb_connect(struct umb_softc *sc)
2461
{
2462
	struct ifnet *ifp = GET_IFP(sc);
2463
2464
	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
2465
		log(LOG_INFO, "%s: connection disabled in roaming network\n",
2466
		    DEVNAM(sc));
2467
		return;
2468
	}
2469
	if (ifp->if_flags & IFF_DEBUG)
2470
		log(LOG_DEBUG, "%s: connecting ...\n", DEVNAM(sc));
2471
	umb_send_connect(sc, MBIM_CONNECT_ACTIVATE);
2472
}
2473
2474
static void
2475
umb_disconnect(struct umb_softc *sc)
2476
{
2477
	struct ifnet *ifp = GET_IFP(sc);
2478
2479
	if (ifp->if_flags & IFF_DEBUG)
2480
		log(LOG_DEBUG, "%s: disconnecting ...\n", DEVNAM(sc));
2481
	umb_send_connect(sc, MBIM_CONNECT_DEACTIVATE);
2482
}
2483
2484
static void
2485
umb_send_connect(struct umb_softc *sc, int command)
2486
{
2487
	struct mbim_cid_connect *c;
2488
	int	 off;
2489
2490
	/* Too large for the stack */
2491
	mtx_unlock(&sc->sc_mutex);
2492
	c = malloc(sizeof (*c), M_MBIM_CID_CONNECT, M_WAITOK | M_ZERO);
2493
	mtx_lock(&sc->sc_mutex);
2494
	c->sessionid = htole32(umb_session_id);
2495
	c->command = htole32(command);
2496
	off = offsetof(struct mbim_cid_connect, data);
2497
	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.apn,
2498
	    sc->sc_info.apnlen, &c->access_offs, &c->access_size))
2499
		goto done;
2500
	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.username,
2501
	    sc->sc_info.usernamelen, &c->user_offs, &c->user_size))
2502
		goto done;
2503
	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.password,
2504
	    sc->sc_info.passwordlen, &c->passwd_offs, &c->passwd_size))
2505
		goto done;
2506
	c->authprot = htole32(MBIM_AUTHPROT_NONE);
2507
	c->compression = htole32(MBIM_COMPRESSION_NONE);
2508
	c->iptype = htole32(MBIM_CONTEXT_IPTYPE_IPV4);
2509
	memcpy(c->context, umb_uuid_context_internet, sizeof (c->context));
2510
	umb_cmd(sc, MBIM_CID_CONNECT, MBIM_CMDOP_SET, c, off);
2511
done:
2512
	free(c, M_MBIM_CID_CONNECT);
2513
	return;
2514
}
2515
2516
static void
2517
umb_qry_ipconfig(struct umb_softc *sc)
2518
{
2519
	struct mbim_cid_ip_configuration_info ipc;
2520
2521
	memset(&ipc, 0, sizeof (ipc));
2522
	ipc.sessionid = htole32(umb_session_id);
2523
	umb_cmd(sc, MBIM_CID_IP_CONFIGURATION, MBIM_CMDOP_QRY,
2524
	    &ipc, sizeof (ipc));
2525
}
2526
2527
static void
2528
umb_cmd(struct umb_softc *sc, int cid, int op, const void *data, int len)
2529
{
2530
	umb_cmd1(sc, cid, op, data, len, umb_uuid_basic_connect);
2531
}
2532
2533
static void
2534
umb_cmd1(struct umb_softc *sc, int cid, int op, const void *data, int len,
2535
    uint8_t *uuid)
2536
{
2537
	struct mbim_h2f_cmd *cmd;
2538
	int	totlen;
2539
2540
	/* XXX FIXME support sending fragments */
2541
	if (sizeof (*cmd) + len > sc->sc_ctrl_len) {
2542
		DPRINTF("set %s msg too long: cannot send\n",
2543
		    umb_cid2str(cid));
2544
		return;
2545
	}
2546
	cmd = sc->sc_ctrl_msg;
2547
	memset(cmd, 0, sizeof (*cmd));
2548
	cmd->frag.nfrag = htole32(1);
2549
	memcpy(cmd->devid, uuid, sizeof (cmd->devid));
2550
	cmd->cid = htole32(cid);
2551
	cmd->op = htole32(op);
2552
	cmd->infolen = htole32(len);
2553
	totlen = sizeof (*cmd);
2554
	if (len > 0) {
2555
		memcpy(cmd + 1, data, len);
2556
		totlen += len;
2557
	}
2558
	umb_ctrl_msg(sc, MBIM_COMMAND_MSG, cmd, totlen);
2559
}
2560
2561
static void
2562
umb_command_done(struct umb_softc *sc, void *data, int len)
2563
{
2564
	struct mbim_f2h_cmddone *cmd = data;
2565
	struct ifnet *ifp = GET_IFP(sc);
2566
	uint32_t status;
2567
	uint32_t cid;
2568
	uint32_t infolen;
2569
	int	 qmimsg = 0;
2570
2571
	if (len < sizeof (*cmd)) {
2572
		DPRINTF("discard short %s message\n",
2573
		    umb_request2str(le32toh(cmd->hdr.type)));
2574
		return;
2575
	}
2576
	cid = le32toh(cmd->cid);
2577
	if (memcmp(cmd->devid, umb_uuid_basic_connect, sizeof (cmd->devid))) {
2578
		if (memcmp(cmd->devid, umb_uuid_qmi_mbim,
2579
		    sizeof (cmd->devid))) {
2580
			DPRINTF("discard %s message for other UUID '%s'\n",
2581
			    umb_request2str(le32toh(cmd->hdr.type)),
2582
			    umb_uuid2str(cmd->devid));
2583
			return;
2584
		} else
2585
			qmimsg = 1;
2586
	}
2587
2588
	status = le32toh(cmd->status);
2589
	switch (status) {
2590
	case MBIM_STATUS_SUCCESS:
2591
		break;
2592
	case MBIM_STATUS_NOT_INITIALIZED:
2593
		if (ifp->if_flags & IFF_DEBUG)
2594
			log(LOG_ERR, "%s: SIM not initialized (PIN missing)\n",
2595
			    DEVNAM(sc));
2596
		return;
2597
	case MBIM_STATUS_PIN_REQUIRED:
2598
		sc->sc_info.pin_state = UMB_PIN_REQUIRED;
2599
		/*FALLTHROUGH*/
2600
	default:
2601
		if (ifp->if_flags & IFF_DEBUG)
2602
			log(LOG_ERR, "%s: set/qry %s failed: %s\n", DEVNAM(sc),
2603
			    umb_cid2str(cid), umb_status2str(status));
2604
		return;
2605
	}
2606
2607
	infolen = le32toh(cmd->infolen);
2608
	if (len < sizeof (*cmd) + infolen) {
2609
		DPRINTF("discard truncated %s message (want %d, got %d)\n",
2610
		    umb_cid2str(cid),
2611
		    (int)sizeof (*cmd) + infolen, len);
2612
		return;
2613
	}
2614
	if (qmimsg) {
2615
		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED)
2616
			umb_decode_qmi(sc, cmd->info, infolen);
2617
	} else {
2618
		DPRINTFN(2, "set/qry %s done\n",
2619
		    umb_cid2str(cid));
2620
		umb_decode_cid(sc, cid, cmd->info, infolen);
2621
	}
2622
}
2623
2624
static void
2625
umb_decode_cid(struct umb_softc *sc, uint32_t cid, void *data, int len)
2626
{
2627
	int	 ok = 1;
2628
2629
	switch (cid) {
2630
	case MBIM_CID_DEVICE_CAPS:
2631
		ok = umb_decode_devices_caps(sc, data, len);
2632
		break;
2633
	case MBIM_CID_SUBSCRIBER_READY_STATUS:
2634
		ok = umb_decode_subscriber_status(sc, data, len);
2635
		break;
2636
	case MBIM_CID_RADIO_STATE:
2637
		ok = umb_decode_radio_state(sc, data, len);
2638
		break;
2639
	case MBIM_CID_PIN:
2640
		ok = umb_decode_pin(sc, data, len);
2641
		break;
2642
	case MBIM_CID_REGISTER_STATE:
2643
		ok = umb_decode_register_state(sc, data, len);
2644
		break;
2645
	case MBIM_CID_PACKET_SERVICE:
2646
		ok = umb_decode_packet_service(sc, data, len);
2647
		break;
2648
	case MBIM_CID_SIGNAL_STATE:
2649
		ok = umb_decode_signal_state(sc, data, len);
2650
		break;
2651
	case MBIM_CID_CONNECT:
2652
		ok = umb_decode_connect_info(sc, data, len);
2653
		break;
2654
	case MBIM_CID_IP_CONFIGURATION:
2655
		ok = umb_decode_ip_configuration(sc, data, len);
2656
		break;
2657
	default:
2658
		/*
2659
		 * Note: the above list is incomplete and only contains
2660
		 *	mandatory CIDs from the BASIC_CONNECT set.
2661
		 *	So alternate values are not unusual.
2662
		 */
2663
		DPRINTFN(4, "ignore %s\n", umb_cid2str(cid));
2664
		break;
2665
	}
2666
	if (!ok)
2667
		DPRINTF("discard %s with bad info length %d\n",
2668
		    umb_cid2str(cid), len);
2669
	return;
2670
}
2671
2672
static void
2673
umb_decode_qmi(struct umb_softc *sc, uint8_t *data, int len)
2674
{
2675
	uint8_t	srv;
2676
	uint16_t msg, tlvlen;
2677
	uint32_t val;
2678
2679
#define UMB_QMI_QMUXLEN		6
2680
	if (len < UMB_QMI_QMUXLEN)
2681
		goto tooshort;
2682
2683
	srv = data[4];
2684
	data += UMB_QMI_QMUXLEN;
2685
	len -= UMB_QMI_QMUXLEN;
2686
2687
#define UMB_GET16(p)	((uint16_t)*p | (uint16_t)*(p + 1) << 8)
2688
#define UMB_GET32(p)	((uint32_t)*p | (uint32_t)*(p + 1) << 8 | \
2689
			    (uint32_t)*(p + 2) << 16 |(uint32_t)*(p + 3) << 24)
2690
	switch (srv) {
2691
	case 0:	/* ctl */
2692
#define UMB_QMI_CTLLEN		6
2693
		if (len < UMB_QMI_CTLLEN)
2694
			goto tooshort;
2695
		msg = UMB_GET16(&data[2]);
2696
		tlvlen = UMB_GET16(&data[4]);
2697
		data += UMB_QMI_CTLLEN;
2698
		len -= UMB_QMI_CTLLEN;
2699
		break;
2700
	case 2:	/* dms  */
2701
#define UMB_QMI_DMSLEN		7
2702
		if (len < UMB_QMI_DMSLEN)
2703
			goto tooshort;
2704
		msg = UMB_GET16(&data[3]);
2705
		tlvlen = UMB_GET16(&data[5]);
2706
		data += UMB_QMI_DMSLEN;
2707
		len -= UMB_QMI_DMSLEN;
2708
		break;
2709
	default:
2710
		DPRINTF("discard QMI message for unknown service type %d\n",
2711
		    srv);
2712
		return;
2713
	}
2714
2715
	if (len < tlvlen)
2716
		goto tooshort;
2717
2718
#define UMB_QMI_TLVLEN		3
2719
	while (len > 0) {
2720
		if (len < UMB_QMI_TLVLEN)
2721
			goto tooshort;
2722
		tlvlen = UMB_GET16(&data[1]);
2723
		if (len < UMB_QMI_TLVLEN + tlvlen)
2724
			goto tooshort;
2725
		switch (data[0]) {
2726
		case 1:	/* allocation info */
2727
			if (msg == 0x0022) {	/* Allocate CID */
2728
				if (tlvlen != 2 || data[3] != 2) /* dms */
2729
					break;
2730
				sc->sc_cid = data[4];
2731
				DPRINTF("QMI CID %d allocated\n",
2732
				    sc->sc_cid);
2733
				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
2734
			}
2735
			break;
2736
		case 2:	/* response */
2737
			if (tlvlen != sizeof (val))
2738
				break;
2739
			val = UMB_GET32(&data[3]);
2740
			switch (msg) {
2741
			case 0x0022:	/* Allocate CID */
2742
				if (val != 0) {
2743
					log(LOG_ERR, "%s: allocation of QMI CID"
2744
					    " failed, error 0x%x\n", DEVNAM(sc),
2745
					    val);
2746
					/* XXX how to proceed? */
2747
					return;
2748
				}
2749
				break;
2750
			case 0x555f:	/* Send FCC Authentication */
2751
				if (val == 0)
2752
					DPRINTF("%s: send FCC "
2753
					    "Authentication succeeded\n",
2754
					    DEVNAM(sc));
2755
				else if (val == 0x001a0001)
2756
					DPRINTF("%s: FCC Authentication "
2757
					    "not required\n", DEVNAM(sc));
2758
				else
2759
					log(LOG_INFO, "%s: send FCC "
2760
					    "Authentication failed, "
2761
					    "error 0x%x\n", DEVNAM(sc), val);
2762
2763
				/* FCC Auth is needed only once after power-on*/
2764
				sc->sc_flags &= ~UMBFLG_FCC_AUTH_REQUIRED;
2765
2766
				/* Try to proceed anyway */
2767
				DPRINTF("init: turning radio on ...\n");
2768
				umb_radio(sc, 1);
2769
				break;
2770
			default:
2771
				break;
2772
			}
2773
			break;
2774
		default:
2775
			break;
2776
		}
2777
		data += UMB_QMI_TLVLEN + tlvlen;
2778
		len -= UMB_QMI_TLVLEN + tlvlen;
2779
	}
2780
	return;
2781
2782
tooshort:
2783
	DPRINTF("discard short QMI message\n");
2784
	return;
2785
}
2786
2787
static void
2788
umb_intr(struct usb_xfer *xfer, usb_error_t status)
2789
{
2790
	struct umb_softc *sc = usbd_xfer_softc(xfer);
2791
	struct usb_cdc_notification notification;
2792
	struct usb_page_cache *pc;
2793
	struct ifnet *ifp = GET_IFP(sc);
2794
	int	 total_len;
2795
2796
	mtx_assert(&sc->sc_mutex, MA_OWNED);
2797
2798
	/* FIXME use actlen or total_len? */
2799
	usbd_xfer_status(xfer, &total_len, NULL, NULL, NULL);
2800
2801
	switch (USB_GET_STATE(xfer)) {
2802
	case USB_ST_TRANSFERRED:
2803
		DPRINTF("Received %d bytes\n", total_len);
2804
2805
		if (total_len < UCDC_NOTIFICATION_LENGTH) {
2806
			DPRINTF("short notification (%d<%d)\n",
2807
					total_len, UCDC_NOTIFICATION_LENGTH);
2808
			return;
2809
		}
2810
2811
		pc = usbd_xfer_get_frame(xfer, 0);
2812
		usbd_copy_out(pc, 0, &notification, sizeof (notification));
2813
2814
		if (notification.bmRequestType != UCDC_NOTIFICATION) {
2815
			DPRINTF("unexpected notification (type=0x%02x)\n",
2816
					notification.bmRequestType);
2817
			return;
2818
		}
2819
2820
		switch (notification.bNotification) {
2821
		case UCDC_N_NETWORK_CONNECTION:
2822
			if (ifp->if_flags & IFF_DEBUG)
2823
				log(LOG_DEBUG, "%s: network %sconnected\n",
2824
						DEVNAM(sc),
2825
						UGETW(notification.wValue)
2826
						? "" : "dis");
2827
			break;
2828
		case UCDC_N_RESPONSE_AVAILABLE:
2829
			DPRINTFN(2, "umb_intr: response available\n");
2830
			++sc->sc_nresp;
2831
			umb_add_task(sc, umb_get_response_task,
2832
					&sc->sc_proc_get_response_task[0].hdr,
2833
					&sc->sc_proc_get_response_task[1].hdr,
2834
					0);
2835
			break;
2836
		case UCDC_N_CONNECTION_SPEED_CHANGE:
2837
			DPRINTFN(2, "umb_intr: connection speed changed\n");
2838
			break;
2839
		default:
2840
			DPRINTF("unexpected notification (0x%02x)\n",
2841
					notification.bNotification);
2842
			break;
2843
		}
2844
		/* fallthrough */
2845
	case USB_ST_SETUP:
2846
tr_setup:
2847
		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
2848
		usbd_transfer_submit(xfer);
2849
		break;
2850
	default:
2851
		if (status != USB_ERR_CANCELLED) {
2852
			/* start clear stall */
2853
			usbd_xfer_set_stall(xfer);
2854
			goto tr_setup;
2855
		}
2856
		break;
2857
	}
2858
}
2859
2860
/*
2861
 * Diagnostic routines
2862
 */
2863
static char *
2864
umb_ntop(struct sockaddr *sa)
2865
{
2866
#define NUMBUFS		4
2867
	static char astr[NUMBUFS][INET_ADDRSTRLEN];
2868
	static unsigned nbuf = 0;
2869
	char	*s;
2870
2871
	s = astr[nbuf++];
2872
	if (nbuf >= NUMBUFS)
2873
		nbuf = 0;
2874
2875
	switch (sa->sa_family) {
2876
	case AF_INET:
2877
	default:
2878
		inet_ntop(AF_INET, &satosin(sa)->sin_addr, s, sizeof (astr[0]));
2879
		break;
2880
	case AF_INET6:
2881
		inet_ntop(AF_INET6, &satosin6(sa)->sin6_addr, s,
2882
		    sizeof (astr[0]));
2883
		break;
2884
	}
2885
	return s;
2886
}
2887
2888
#ifdef UMB_DEBUG
2889
static char *
2890
umb_uuid2str(uint8_t uuid[MBIM_UUID_LEN])
2891
{
2892
	static char uuidstr[2 * MBIM_UUID_LEN + 5];
2893
2894
#define UUID_BFMT	"%02X"
2895
#define UUID_SEP	"-"
2896
	snprintf(uuidstr, sizeof (uuidstr),
2897
	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_SEP
2898
	    UUID_BFMT UUID_BFMT UUID_SEP
2899
	    UUID_BFMT UUID_BFMT UUID_SEP
2900
	    UUID_BFMT UUID_BFMT UUID_SEP
2901
	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT,
2902
	    uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
2903
	    uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
2904
	    uuid[12], uuid[13], uuid[14], uuid[15]);
2905
	return uuidstr;
2906
}
2907
2908
static void
2909
umb_dump(void *buf, int len)
2910
{
2911
	int	 i = 0;
2912
	uint8_t	*c = buf;
2913
2914
	if (len == 0)
2915
		return;
2916
	while (i < len) {
2917
		if ((i % 16) == 0) {
2918
			if (i > 0)
2919
				log(LOG_DEBUG, "\n");
2920
			log(LOG_DEBUG, "%4d:  ", i);
2921
		}
2922
		log(LOG_DEBUG, " %02x", *c);
2923
		c++;
2924
		i++;
2925
	}
2926
	log(LOG_DEBUG, "\n");
2927
}
2928
#endif /* UMB_DEBUG */
2929
2930
DRIVER_MODULE(umb, uhub, umb_driver, NULL, NULL);
2931
MODULE_DEPEND(umb, usb, 1, 1, 1);
(-)b/sys/dev/usb/net/if_umbreg.h (+441 lines)
Added Link Here
1
/*	$OpenBSD: if_umb.h,v 1.4 2017/04/18 13:27:55 gerhard Exp $ */
2
3
/*
4
 * Original copyright (c) 2016 genua mbH (OpenBSD version)
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 *
18
 * Copyright (c) 2022 ADISTA SAS (re-write for FreeBSD)
19
 *
20
 * Re-write for FreeBSD by Pierre Pronchery <pierre@defora.net>
21
 *
22
 * Redistribution and use in source and binary forms, with or without
23
 * modification, are permitted provided that the following conditions are met:
24
 *
25
 * - Redistributions of source code must retain the above copyright notice,
26
 *   this list of conditions and the following disclaimer.
27
 * - Redistributions in binary form must reproduce the above copyright notice,
28
 *   this list of conditions and the following disclaimer in the documentation
29
 *   and/or other materials provided with the distribution.
30
 * - Neither the name of the copyright holder nor the names of its contributors
31
 *   may be used to endorse or promote products derived from this software
32
 *   without specific prior written permission.
33
 *
34
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
35
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
38
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44
 * POSSIBILITY OF SUCH DAMAGE.
45
 */
46
47
/*
48
 * Mobile Broadband Interface Model
49
 * http://www.usb.org/developers/docs/devclass_docs/MBIM-Compliance-1.0.pdf
50
 */
51
52
struct umb_valdescr {
53
	int		 val;
54
	char const	*descr;
55
};
56
57
static const char *
58
umb_val2descr(const struct umb_valdescr *vdp, int val)
59
{
60
	static char sval[32];
61
62
	while (vdp->descr != NULL) {
63
		if (vdp->val == val)
64
			return vdp->descr;
65
		vdp++;
66
	}
67
	snprintf(sval, sizeof (sval), "#%d", val);
68
	return sval;
69
}
70
71
#define MBIM_REGSTATE_DESCRIPTIONS {				\
72
	{ MBIM_REGSTATE_UNKNOWN,	"unknown" },		\
73
	{ MBIM_REGSTATE_DEREGISTERED,	"not registered" },	\
74
	{ MBIM_REGSTATE_SEARCHING,	"searching" },		\
75
	{ MBIM_REGSTATE_HOME,		"home network" },	\
76
	{ MBIM_REGSTATE_ROAMING,	"roaming network" },	\
77
	{ MBIM_REGSTATE_PARTNER,	"partner network" },	\
78
	{ MBIM_REGSTATE_DENIED,		"access denied" },	\
79
	{ 0, NULL } }
80
81
#define MBIM_DATACLASS_DESCRIPTIONS {					\
82
	{ MBIM_DATACLASS_NONE,				"none" },	\
83
	{ MBIM_DATACLASS_GPRS,				"GPRS" },	\
84
	{ MBIM_DATACLASS_EDGE,				"EDGE" },	\
85
	{ MBIM_DATACLASS_UMTS,				"UMTS" },	\
86
	{ MBIM_DATACLASS_HSDPA,				"HSDPA" },	\
87
	{ MBIM_DATACLASS_HSUPA,				"HSUPA" },	\
88
	{ MBIM_DATACLASS_HSDPA|MBIM_DATACLASS_HSUPA,	"HSPA" },	\
89
	{ MBIM_DATACLASS_LTE,				"LTE" },	\
90
	{ MBIM_DATACLASS_1XRTT,				"CDMA2000" },	\
91
	{ MBIM_DATACLASS_1XEVDO,			"CDMA2000" },	\
92
	{ MBIM_DATACLASS_1XEVDO_REV_A,			"CDMA2000" },	\
93
	{ MBIM_DATACLASS_1XEVDV,			"CDMA2000" },	\
94
	{ MBIM_DATACLASS_3XRTT,				"CDMA2000" },	\
95
	{ MBIM_DATACLASS_1XEVDO_REV_B,			"CDMA2000" },	\
96
	{ MBIM_DATACLASS_UMB,				"CDMA2000" },	\
97
	{ MBIM_DATACLASS_CUSTOM,			"custom" },	\
98
	{ 0, NULL } }
99
100
#define MBIM_1TO1_DESCRIPTION(m)	{ (m), #m }
101
#define MBIM_MESSAGES_DESCRIPTIONS {				\
102
	MBIM_1TO1_DESCRIPTION(MBIM_OPEN_MSG),			\
103
	MBIM_1TO1_DESCRIPTION(MBIM_CLOSE_MSG),			\
104
	MBIM_1TO1_DESCRIPTION(MBIM_COMMAND_MSG),		\
105
	MBIM_1TO1_DESCRIPTION(MBIM_HOST_ERROR_MSG),		\
106
	MBIM_1TO1_DESCRIPTION(MBIM_OPEN_DONE),			\
107
	MBIM_1TO1_DESCRIPTION(MBIM_CLOSE_DONE),			\
108
	MBIM_1TO1_DESCRIPTION(MBIM_COMMAND_DONE),		\
109
	MBIM_1TO1_DESCRIPTION(MBIM_FUNCTION_ERROR_MSG),		\
110
	MBIM_1TO1_DESCRIPTION(MBIM_INDICATE_STATUS_MSG),	\
111
	{ 0, NULL } }
112
113
#define MBIM_STATUS_DESCRIPTION(m)	{ MBIM_STATUS_ ## m, #m }
114
#define MBIM_STATUS_DESCRIPTIONS {					\
115
	MBIM_STATUS_DESCRIPTION(SUCCESS),				\
116
	MBIM_STATUS_DESCRIPTION(BUSY),					\
117
	MBIM_STATUS_DESCRIPTION(FAILURE),				\
118
	MBIM_STATUS_DESCRIPTION(SIM_NOT_INSERTED),			\
119
	MBIM_STATUS_DESCRIPTION(BAD_SIM),				\
120
	MBIM_STATUS_DESCRIPTION(PIN_REQUIRED),				\
121
	MBIM_STATUS_DESCRIPTION(PIN_DISABLED),				\
122
	MBIM_STATUS_DESCRIPTION(NOT_REGISTERED),			\
123
	MBIM_STATUS_DESCRIPTION(PROVIDERS_NOT_FOUND),			\
124
	MBIM_STATUS_DESCRIPTION(NO_DEVICE_SUPPORT),			\
125
	MBIM_STATUS_DESCRIPTION(PROVIDER_NOT_VISIBLE),			\
126
	MBIM_STATUS_DESCRIPTION(DATA_CLASS_NOT_AVAILABLE),		\
127
	MBIM_STATUS_DESCRIPTION(PACKET_SERVICE_DETACHED),		\
128
	MBIM_STATUS_DESCRIPTION(MAX_ACTIVATED_CONTEXTS),		\
129
	MBIM_STATUS_DESCRIPTION(NOT_INITIALIZED),			\
130
	MBIM_STATUS_DESCRIPTION(VOICE_CALL_IN_PROGRESS),		\
131
	MBIM_STATUS_DESCRIPTION(CONTEXT_NOT_ACTIVATED),			\
132
	MBIM_STATUS_DESCRIPTION(SERVICE_NOT_ACTIVATED),			\
133
	MBIM_STATUS_DESCRIPTION(INVALID_ACCESS_STRING),			\
134
	MBIM_STATUS_DESCRIPTION(INVALID_USER_NAME_PWD),			\
135
	MBIM_STATUS_DESCRIPTION(RADIO_POWER_OFF),			\
136
	MBIM_STATUS_DESCRIPTION(INVALID_PARAMETERS),			\
137
	MBIM_STATUS_DESCRIPTION(READ_FAILURE),				\
138
	MBIM_STATUS_DESCRIPTION(WRITE_FAILURE),				\
139
	MBIM_STATUS_DESCRIPTION(NO_PHONEBOOK),				\
140
	MBIM_STATUS_DESCRIPTION(PARAMETER_TOO_LONG),			\
141
	MBIM_STATUS_DESCRIPTION(STK_BUSY),				\
142
	MBIM_STATUS_DESCRIPTION(OPERATION_NOT_ALLOWED),			\
143
	MBIM_STATUS_DESCRIPTION(MEMORY_FAILURE),			\
144
	MBIM_STATUS_DESCRIPTION(INVALID_MEMORY_INDEX),			\
145
	MBIM_STATUS_DESCRIPTION(MEMORY_FULL),				\
146
	MBIM_STATUS_DESCRIPTION(FILTER_NOT_SUPPORTED),			\
147
	MBIM_STATUS_DESCRIPTION(DSS_INSTANCE_LIMIT),			\
148
	MBIM_STATUS_DESCRIPTION(INVALID_DEVICE_SERVICE_OPERATION),	\
149
	MBIM_STATUS_DESCRIPTION(AUTH_INCORRECT_AUTN),			\
150
	MBIM_STATUS_DESCRIPTION(AUTH_SYNC_FAILURE),			\
151
	MBIM_STATUS_DESCRIPTION(AUTH_AMF_NOT_SET),			\
152
	MBIM_STATUS_DESCRIPTION(CONTEXT_NOT_SUPPORTED),			\
153
	MBIM_STATUS_DESCRIPTION(SMS_UNKNOWN_SMSC_ADDRESS),		\
154
	MBIM_STATUS_DESCRIPTION(SMS_NETWORK_TIMEOUT),			\
155
	MBIM_STATUS_DESCRIPTION(SMS_LANG_NOT_SUPPORTED),		\
156
	MBIM_STATUS_DESCRIPTION(SMS_ENCODING_NOT_SUPPORTED),		\
157
	MBIM_STATUS_DESCRIPTION(SMS_FORMAT_NOT_SUPPORTED),		\
158
	{ 0, NULL } }
159
160
#define MBIM_ERROR_DESCRIPTION(m)	{ MBIM_ERROR_ ## m, #m }
161
#define MBIM_ERROR_DESCRIPTIONS {					\
162
	MBIM_ERROR_DESCRIPTION(TIMEOUT_FRAGMENT),			\
163
	MBIM_ERROR_DESCRIPTION(FRAGMENT_OUT_OF_SEQUENCE),		\
164
	MBIM_ERROR_DESCRIPTION(LENGTH_MISMATCH),			\
165
	MBIM_ERROR_DESCRIPTION(DUPLICATED_TID),				\
166
	MBIM_ERROR_DESCRIPTION(NOT_OPENED),				\
167
	MBIM_ERROR_DESCRIPTION(UNKNOWN),				\
168
	MBIM_ERROR_DESCRIPTION(CANCEL),					\
169
	MBIM_ERROR_DESCRIPTION(MAX_TRANSFER),				\
170
	{ 0, NULL } }
171
172
#define MBIM_CID_DESCRIPTIONS {						\
173
	MBIM_1TO1_DESCRIPTION(MBIM_CID_DEVICE_CAPS),			\
174
	MBIM_1TO1_DESCRIPTION(MBIM_CID_SUBSCRIBER_READY_STATUS),	\
175
	MBIM_1TO1_DESCRIPTION(MBIM_CID_RADIO_STATE),			\
176
	MBIM_1TO1_DESCRIPTION(MBIM_CID_PIN),				\
177
	MBIM_1TO1_DESCRIPTION(MBIM_CID_PIN_LIST),			\
178
	MBIM_1TO1_DESCRIPTION(MBIM_CID_HOME_PROVIDER),			\
179
	MBIM_1TO1_DESCRIPTION(MBIM_CID_PREFERRED_PROVIDERS),		\
180
	MBIM_1TO1_DESCRIPTION(MBIM_CID_VISIBLE_PROVIDERS),		\
181
	MBIM_1TO1_DESCRIPTION(MBIM_CID_REGISTER_STATE),			\
182
	MBIM_1TO1_DESCRIPTION(MBIM_CID_PACKET_SERVICE),			\
183
	MBIM_1TO1_DESCRIPTION(MBIM_CID_SIGNAL_STATE),			\
184
	MBIM_1TO1_DESCRIPTION(MBIM_CID_CONNECT),			\
185
	MBIM_1TO1_DESCRIPTION(MBIM_CID_PROVISIONED_CONTEXTS),		\
186
	MBIM_1TO1_DESCRIPTION(MBIM_CID_SERVICE_ACTIVATION),		\
187
	MBIM_1TO1_DESCRIPTION(MBIM_CID_IP_CONFIGURATION),		\
188
	MBIM_1TO1_DESCRIPTION(MBIM_CID_DEVICE_SERVICES),		\
189
	MBIM_1TO1_DESCRIPTION(MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST),	\
190
	MBIM_1TO1_DESCRIPTION(MBIM_CID_PACKET_STATISTICS),		\
191
	MBIM_1TO1_DESCRIPTION(MBIM_CID_NETWORK_IDLE_HINT),		\
192
	MBIM_1TO1_DESCRIPTION(MBIM_CID_EMERGENCY_MODE),			\
193
	MBIM_1TO1_DESCRIPTION(MBIM_CID_IP_PACKET_FILTERS),		\
194
	MBIM_1TO1_DESCRIPTION(MBIM_CID_MULTICARRIER_PROVIDERS),		\
195
	{ 0, NULL } }
196
197
#define MBIM_SIMSTATE_DESCRIPTIONS {					\
198
	{ MBIM_SIMSTATE_NOTINITIALIZED, "not initialized" },		\
199
	{ MBIM_SIMSTATE_INITIALIZED, "initialized" },			\
200
	{ MBIM_SIMSTATE_NOTINSERTED, "not inserted" },			\
201
	{ MBIM_SIMSTATE_BADSIM, "bad type" },				\
202
	{ MBIM_SIMSTATE_FAILURE, "failed" },				\
203
	{ MBIM_SIMSTATE_NOTACTIVATED, "not activated" },		\
204
	{ MBIM_SIMSTATE_LOCKED, "locked" },				\
205
	{ 0, NULL } }
206
207
#define MBIM_PINTYPE_DESCRIPTIONS {					\
208
	{ MBIM_PIN_TYPE_NONE, "none" },					\
209
	{ MBIM_PIN_TYPE_CUSTOM, "custom" },				\
210
	{ MBIM_PIN_TYPE_PIN1, "PIN1" },					\
211
	{ MBIM_PIN_TYPE_PIN2, "PIN2" },					\
212
	{ MBIM_PIN_TYPE_DEV_SIM_PIN, "device PIN" },			\
213
	{ MBIM_PIN_TYPE_DEV_FIRST_SIM_PIN, "device 1st PIN" },		\
214
	{ MBIM_PIN_TYPE_NETWORK_PIN, "network PIN" },			\
215
	{ MBIM_PIN_TYPE_NETWORK_SUBSET_PIN, "network subset PIN" },	\
216
	{ MBIM_PIN_TYPE_SERVICE_PROVIDER_PIN, "provider PIN" },		\
217
	{ MBIM_PIN_TYPE_CORPORATE_PIN, "corporate PIN" },		\
218
	{ MBIM_PIN_TYPE_SUBSIDY_LOCK, "subsidy lock" },			\
219
	{ MBIM_PIN_TYPE_PUK1, "PUK" },					\
220
	{ MBIM_PIN_TYPE_PUK2, "PUK2" },					\
221
	{ MBIM_PIN_TYPE_DEV_FIRST_SIM_PUK, "device 1st PUK" },		\
222
	{ MBIM_PIN_TYPE_NETWORK_PUK, "network PUK" },			\
223
	{ MBIM_PIN_TYPE_NETWORK_SUBSET_PUK, "network subset PUK" },	\
224
	{ MBIM_PIN_TYPE_SERVICE_PROVIDER_PUK, "provider PUK" },		\
225
	{ MBIM_PIN_TYPE_CORPORATE_PUK, "corporate PUK" },		\
226
	{ 0, NULL } }
227
228
#define MBIM_PKTSRV_STATE_DESCRIPTIONS {				\
229
	{ MBIM_PKTSERVICE_STATE_UNKNOWN, "unknown" },			\
230
	{ MBIM_PKTSERVICE_STATE_ATTACHING, "attaching" },		\
231
	{ MBIM_PKTSERVICE_STATE_ATTACHED, "attached" },			\
232
	{ MBIM_PKTSERVICE_STATE_DETACHING, "detaching" },		\
233
	{ MBIM_PKTSERVICE_STATE_DETACHED, "detached" },			\
234
	{ 0, NULL } }
235
236
#define MBIM_ACTIVATION_STATE_DESCRIPTIONS {				\
237
	{ MBIM_ACTIVATION_STATE_UNKNOWN, "unknown" },			\
238
	{ MBIM_ACTIVATION_STATE_ACTIVATED, "activated" },		\
239
	{ MBIM_ACTIVATION_STATE_ACTIVATING, "activating" },		\
240
	{ MBIM_ACTIVATION_STATE_DEACTIVATED, "deactivated" },		\
241
	{ MBIM_ACTIVATION_STATE_DEACTIVATING, "deactivating" },		\
242
	{ 0, NULL } }
243
244
/*
245
 * Driver internal state
246
 */
247
enum umb_state {
248
	UMB_S_DOWN = 0,		/* interface down */
249
	UMB_S_OPEN,		/* MBIM device has been opened */
250
	UMB_S_CID,		/* QMI client id allocated */
251
	UMB_S_RADIO,		/* radio is on */
252
	UMB_S_SIMREADY,		/* SIM is ready */
253
	UMB_S_ATTACHED,		/* packet service is attached */
254
	UMB_S_CONNECTED,	/* connected to provider */
255
	UMB_S_UP,		/* have IP configuration */
256
};
257
258
#define UMB_INTERNAL_STATE_DESCRIPTIONS {	\
259
	{ UMB_S_DOWN, "down" },			\
260
	{ UMB_S_OPEN, "open" },			\
261
	{ UMB_S_CID, "CID allocated" },		\
262
	{ UMB_S_RADIO, "radio on" },		\
263
	{ UMB_S_SIMREADY, "SIM is ready" },	\
264
	{ UMB_S_ATTACHED, "attached" },		\
265
	{ UMB_S_CONNECTED, "connected" },	\
266
	{ UMB_S_UP, "up" },			\
267
	{ 0, NULL } }
268
269
/*
270
 * UMB parameters (SIOC[GS]UMBPARAM ioctls)
271
 */
272
struct umb_parameter {
273
	int			op;
274
	int			is_puk;
275
	uint16_t		pin[MBIM_PIN_MAXLEN];
276
	int			pinlen;
277
278
	uint16_t		newpin[MBIM_PIN_MAXLEN];
279
	int			newpinlen;
280
281
#define UMB_APN_MAXLEN		100
282
	uint16_t		apn[UMB_APN_MAXLEN];
283
	int			apnlen;
284
285
#define UMB_USERNAME_MAXLEN	205
286
	uint16_t		username[UMB_USERNAME_MAXLEN];
287
	int			usernamelen;
288
289
#define UMB_PASSWORD_MAXLEN	205
290
	uint16_t		password[UMB_PASSWORD_MAXLEN];
291
	int			passwordlen;
292
293
	int			roaming;
294
	uint32_t		preferredclasses;
295
};
296
297
/*
298
 * UMB device status info (SIOCGUMBINFO ioctl)
299
 */
300
struct umb_info {
301
	enum umb_state		state;
302
	int			enable_roaming;
303
#define UMB_PIN_REQUIRED	0
304
#define UMB_PIN_UNLOCKED	1
305
#define UMB_PUK_REQUIRED	2
306
	int			pin_state;
307
	int			pin_attempts_left;
308
	int			activation;
309
	int			sim_state;
310
	int			regstate;
311
	int			regmode;
312
	int			nwerror;
313
	int			packetstate;
314
	uint32_t		supportedclasses; /* what the hw supports */
315
	uint32_t		preferredclasses; /* what the user prefers */
316
	uint32_t		highestclass;	/* what the network offers */
317
	uint32_t		cellclass;
318
#define UMB_PROVIDERNAME_MAXLEN		20
319
	uint16_t		provider[UMB_PROVIDERNAME_MAXLEN];
320
#define UMB_PHONENR_MAXLEN		22
321
	uint16_t		pn[UMB_PHONENR_MAXLEN];
322
#define UMB_SUBSCRIBERID_MAXLEN		15
323
	uint16_t		sid[UMB_SUBSCRIBERID_MAXLEN];
324
#define UMB_ICCID_MAXLEN		20
325
	uint16_t		iccid[UMB_ICCID_MAXLEN];
326
#define UMB_ROAMINGTEXT_MAXLEN		63
327
	uint16_t		roamingtxt[UMB_ROAMINGTEXT_MAXLEN];
328
329
#define UMB_DEVID_MAXLEN		18
330
	uint16_t		devid[UMB_DEVID_MAXLEN];
331
#define UMB_FWINFO_MAXLEN		30
332
	uint16_t		fwinfo[UMB_FWINFO_MAXLEN];
333
#define UMB_HWINFO_MAXLEN		30
334
	uint16_t		hwinfo[UMB_HWINFO_MAXLEN];
335
336
	uint16_t		apn[UMB_APN_MAXLEN];
337
	int			apnlen;
338
339
	uint16_t		username[UMB_USERNAME_MAXLEN];
340
	int			usernamelen;
341
342
	uint16_t		password[UMB_PASSWORD_MAXLEN];
343
	int			passwordlen;
344
345
#define UMB_VALUE_UNKNOWN	-999
346
	int			rssi;
347
#define UMB_BER_EXCELLENT	0
348
#define UMB_BER_VERYGOOD	1
349
#define UMB_BER_GOOD		2
350
#define UMB_BER_OK		3
351
#define UMB_BER_MEDIUM		4
352
#define UMB_BER_BAD		5
353
#define UMB_BER_VERYBAD		6
354
#define UMB_BER_EXTREMELYBAD	7
355
	int			ber;
356
357
	int			hw_radio_on;
358
	int			sw_radio_on;
359
360
	uint64_t		uplink_speed;
361
	uint64_t		downlink_speed;
362
363
#define UMB_MAX_DNSSRV			2
364
	struct in_addr		ipv4dns[UMB_MAX_DNSSRV];
365
};
366
367
#if !defined(ifr_mtu)
368
#define ifr_mtu	ifr_ifru.ifru_metric
369
#endif
370
371
#ifdef _KERNEL
372
/*
373
 * UMB device
374
 */
375
enum {
376
	UMB_INTR_RX,
377
	UMB_BULK_RX,
378
	UMB_BULK_TX,
379
	UMB_N_TRANSFER,
380
};
381
382
struct umb_task {
383
	struct usb_proc_msg	 hdr;
384
	struct umb_softc	*sc;
385
};
386
387
struct umb_softc {
388
	device_t		 sc_dev;
389
	struct ifnet		*sc_if;
390
#define GET_IFP(sc)	((sc)->sc_if)
391
	struct ifmedia		 sc_im;
392
	struct usb_device	*sc_udev;
393
	struct usb_xfer		*sc_xfer[UMB_N_TRANSFER];
394
	uint8_t			 sc_ifaces_index[2];
395
396
	int			 sc_ver_maj;
397
	int			 sc_ver_min;
398
	int			 sc_ctrl_len;
399
	int			 sc_maxpktlen;
400
	int			 sc_maxsessions;
401
402
#define UMBFLG_FCC_AUTH_REQUIRED	0x0001
403
#define UMBFLG_NO_INET6			0x0002
404
	uint32_t		 sc_flags;
405
	int			 sc_cid;
406
407
	struct usb_process	 sc_taskqueue;
408
	struct umb_task		 sc_proc_attach_task[2];
409
	struct umb_task		 sc_proc_start_task[2];
410
	struct umb_task		 sc_proc_state_task[2];
411
	struct umb_task		 sc_proc_get_response_task[2];
412
413
	int			 sc_nresp;
414
	struct mtx		 sc_mutex;
415
	struct usb_callout	 sc_statechg_timer;
416
	char			 sc_dying;
417
	char			 sc_attached;
418
419
	uint8_t			 sc_ctrl_ifaceno;
420
	struct usb_interface	*sc_data_iface;
421
422
	void			*sc_resp_buf;
423
	void			*sc_ctrl_msg;
424
425
	void			*sc_rx_buf;
426
	uint32_t		 sc_rx_bufsz;
427
	unsigned		 sc_rx_nerr;
428
	struct ifqueue		 sc_rx_queue;
429
430
	void			*sc_tx_buf;
431
	struct mbuf		*sc_tx_m;
432
	uint32_t		 sc_tx_bufsz;
433
	uint32_t		 sc_tx_seq;
434
435
	uint32_t		 sc_tid;
436
437
#define sc_state		sc_info.state
438
#define sc_roaming		sc_info.enable_roaming
439
	struct umb_info		 sc_info;
440
};
441
#endif /* _KERNEL */
(-)b/sys/dev/usb/net/mbim.h (+724 lines)
Added Link Here
1
/*	$OpenBSD: mbim.h,v 1.4 2017/04/18 13:27:55 gerhard Exp $ */
2
3
/*
4
 * Original copyright (c) 2016 genua mbH (OpenBSD version)
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 *
18
 * Copyright (c) 2022 ADISTA SAS (re-write for FreeBSD)
19
 *
20
 * Re-write for FreeBSD by Pierre Pronchery <pierre@defora.net>
21
 *
22
 * Redistribution and use in source and binary forms, with or without
23
 * modification, are permitted provided that the following conditions are met:
24
 *
25
 * - Redistributions of source code must retain the above copyright notice,
26
 *   this list of conditions and the following disclaimer.
27
 * - Redistributions in binary form must reproduce the above copyright notice,
28
 *   this list of conditions and the following disclaimer in the documentation
29
 *   and/or other materials provided with the distribution.
30
 * - Neither the name of the copyright holder nor the names of its contributors
31
 *   may be used to endorse or promote products derived from this software
32
 *   without specific prior written permission.
33
 *
34
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
35
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
38
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44
 * POSSIBILITY OF SUCH DAMAGE.
45
 */
46
47
/*
48
 * Mobile Broadband Interface Model
49
 * http://www.usb.org/developers/docs/devclass_docs/MBIM-Compliance-1.0.pdf
50
 */
51
#ifndef _MBIM_H_
52
#define _MBIM_H_
53
54
#define UDESCSUB_MBIM			27
55
#define MBIM_INTERFACE_ALTSETTING	1
56
57
#define MBIM_RESET_FUNCTION		0x05
58
59
/*
60
 * Registration state (MBIM_REGISTER_STATE)
61
 */
62
#define MBIM_REGSTATE_UNKNOWN			0
63
#define MBIM_REGSTATE_DEREGISTERED		1
64
#define MBIM_REGSTATE_SEARCHING			2
65
#define MBIM_REGSTATE_HOME			3
66
#define MBIM_REGSTATE_ROAMING			4
67
#define MBIM_REGSTATE_PARTNER			5
68
#define MBIM_REGSTATE_DENIED			6
69
70
/*
71
 * Data classes mask (MBIM_DATA_CLASS)
72
 */
73
#define MBIM_DATACLASS_NONE			0x00000000
74
#define MBIM_DATACLASS_GPRS			0x00000001
75
#define MBIM_DATACLASS_EDGE			0x00000002
76
#define MBIM_DATACLASS_UMTS			0x00000004
77
#define MBIM_DATACLASS_HSDPA			0x00000008
78
#define MBIM_DATACLASS_HSUPA			0x00000010
79
#define MBIM_DATACLASS_LTE			0x00000020
80
#define MBIM_DATACLASS_1XRTT			0x00010000
81
#define MBIM_DATACLASS_1XEVDO			0x00020000
82
#define MBIM_DATACLASS_1XEVDO_REV_A		0x00040000
83
#define MBIM_DATACLASS_1XEVDV			0x00080000
84
#define MBIM_DATACLASS_3XRTT			0x00100000
85
#define MBIM_DATACLASS_1XEVDO_REV_B		0x00200000
86
#define MBIM_DATACLASS_UMB			0x00400000
87
#define MBIM_DATACLASS_CUSTOM			0x80000000
88
89
/*
90
 * Cell classes mask (MBIM_CELLULAR_CLASS)
91
 */
92
#define MBIM_CELLCLASS_GSM			0x00000001
93
#define MBIM_CELLCLASS_CDMA			0x00000002
94
95
/*
96
 * UUIDs
97
 */
98
#define MBIM_UUID_LEN		16
99
100
#define MBIM_UUID_BASIC_CONNECT {				\
101
		0xa2, 0x89, 0xcc, 0x33, 0xbc, 0xbb, 0x8b, 0x4f,	\
102
		0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf	\
103
	}
104
105
#define MBIM_UUID_CONTEXT_INTERNET {				\
106
		0x7e, 0x5e, 0x2a, 0x7e, 0x4e, 0x6f, 0x72, 0x72,	\
107
		0x73, 0x6b, 0x65, 0x6e, 0x7e, 0x5e, 0x2a, 0x7e	\
108
	}
109
110
#define MBIM_UUID_CONTEXT_VPN {				\
111
		0x9b, 0x9f, 0x7b, 0xbe, 0x89, 0x52, 0x44, 0xb7,	\
112
		0x83, 0xac, 0xca, 0x41, 0x31, 0x8d, 0xf7, 0xa0	\
113
	}
114
115
#define MBIM_UUID_QMI_MBIM {				\
116
		0xd1, 0xa3, 0x0b, 0xc2, 0xf9, 0x7a, 0x6e, 0x43,	\
117
		0xbf, 0x65, 0xc7, 0xe2, 0x4f, 0xb0, 0xf0, 0xd3	\
118
	}
119
120
#define MBIM_CTRLMSG_MINLEN		64
121
#define MBIM_CTRLMSG_MAXLEN		(4 * 1204)
122
123
#define MBIM_MAXSEGSZ_MINVAL		(2 * 1024)
124
125
/*
126
 * Control messages (host to function)
127
 */
128
#define MBIM_OPEN_MSG			1U
129
#define MBIM_CLOSE_MSG			2U
130
#define MBIM_COMMAND_MSG		3U
131
#define MBIM_HOST_ERROR_MSG		4U
132
133
/*
134
 * Control messages (function to host)
135
 */
136
#define MBIM_OPEN_DONE			0x80000001U
137
#define MBIM_CLOSE_DONE			0x80000002U
138
#define MBIM_COMMAND_DONE		0x80000003U
139
#define MBIM_FUNCTION_ERROR_MSG		0x80000004U
140
#define MBIM_INDICATE_STATUS_MSG	0x80000007U
141
142
/*
143
 * Generic status codes
144
 */
145
#define MBIM_STATUS_SUCCESS			0
146
#define MBIM_STATUS_BUSY			1
147
#define MBIM_STATUS_FAILURE			2
148
#define MBIM_STATUS_SIM_NOT_INSERTED		3
149
#define MBIM_STATUS_BAD_SIM			4
150
#define MBIM_STATUS_PIN_REQUIRED		5
151
#define MBIM_STATUS_PIN_DISABLED		6
152
#define MBIM_STATUS_NOT_REGISTERED		7
153
#define MBIM_STATUS_PROVIDERS_NOT_FOUND		8
154
#define MBIM_STATUS_NO_DEVICE_SUPPORT		9
155
#define MBIM_STATUS_PROVIDER_NOT_VISIBLE	10
156
#define MBIM_STATUS_DATA_CLASS_NOT_AVAILABLE	11
157
#define MBIM_STATUS_PACKET_SERVICE_DETACHED	12
158
#define MBIM_STATUS_MAX_ACTIVATED_CONTEXTS	13
159
#define MBIM_STATUS_NOT_INITIALIZED		14
160
#define MBIM_STATUS_VOICE_CALL_IN_PROGRESS	15
161
#define MBIM_STATUS_CONTEXT_NOT_ACTIVATED	16
162
#define MBIM_STATUS_SERVICE_NOT_ACTIVATED	17
163
#define MBIM_STATUS_INVALID_ACCESS_STRING	18
164
#define MBIM_STATUS_INVALID_USER_NAME_PWD	19
165
#define MBIM_STATUS_RADIO_POWER_OFF		20
166
#define MBIM_STATUS_INVALID_PARAMETERS		21
167
#define MBIM_STATUS_READ_FAILURE		22
168
#define MBIM_STATUS_WRITE_FAILURE		23
169
#define MBIM_STATUS_NO_PHONEBOOK		25
170
#define MBIM_STATUS_PARAMETER_TOO_LONG		26
171
#define MBIM_STATUS_STK_BUSY			27
172
#define MBIM_STATUS_OPERATION_NOT_ALLOWED	28
173
#define MBIM_STATUS_MEMORY_FAILURE		29
174
#define MBIM_STATUS_INVALID_MEMORY_INDEX	30
175
#define MBIM_STATUS_MEMORY_FULL			31
176
#define MBIM_STATUS_FILTER_NOT_SUPPORTED	32
177
#define MBIM_STATUS_DSS_INSTANCE_LIMIT		33
178
#define MBIM_STATUS_INVALID_DEVICE_SERVICE_OPERATION	34
179
#define MBIM_STATUS_AUTH_INCORRECT_AUTN		35
180
#define MBIM_STATUS_AUTH_SYNC_FAILURE		36
181
#define MBIM_STATUS_AUTH_AMF_NOT_SET		37
182
#define MBIM_STATUS_CONTEXT_NOT_SUPPORTED	38
183
#define MBIM_STATUS_SMS_UNKNOWN_SMSC_ADDRESS	100
184
#define MBIM_STATUS_SMS_NETWORK_TIMEOUT		101
185
#define MBIM_STATUS_SMS_LANG_NOT_SUPPORTED	102
186
#define MBIM_STATUS_SMS_ENCODING_NOT_SUPPORTED	103
187
#define MBIM_STATUS_SMS_FORMAT_NOT_SUPPORTED	104
188
189
/*
190
 * Message formats
191
 */
192
struct mbim_msghdr {
193
	/* Msg header */
194
	uint32_t	type;		/* message type */
195
	uint32_t	len;		/* message length */
196
	uint32_t	tid;		/* transaction id */
197
} __packed;
198
199
struct mbim_fraghdr {
200
	uint32_t	nfrag;		/* total # of fragments */
201
	uint32_t	currfrag;	/* current fragment */
202
} __packed;
203
204
struct mbim_fragmented_msg_hdr {
205
	struct mbim_msghdr	hdr;
206
	struct mbim_fraghdr	frag;
207
} __packed;
208
209
struct mbim_h2f_openmsg {
210
	struct mbim_msghdr	hdr;
211
	uint32_t		maxlen;
212
} __packed;
213
214
struct mbim_h2f_closemsg {
215
	struct mbim_msghdr	hdr;
216
} __packed;
217
218
struct mbim_h2f_cmd {
219
	struct mbim_msghdr	hdr;
220
	struct mbim_fraghdr	frag;
221
	uint8_t			devid[MBIM_UUID_LEN];
222
	uint32_t		cid;		/* command id */
223
#define MBIM_CMDOP_QRY		0
224
#define MBIM_CMDOP_SET		1
225
	uint32_t		op;
226
	uint32_t		infolen;
227
	uint8_t			info[];
228
} __packed;
229
230
struct mbim_f2h_indicate_status {
231
	struct mbim_msghdr	hdr;
232
	struct mbim_fraghdr	frag;
233
	uint8_t			devid[MBIM_UUID_LEN];
234
	uint32_t		cid;		/* command id */
235
	uint32_t		infolen;
236
	uint8_t			info[];
237
} __packed;
238
239
struct mbim_f2h_hosterr {
240
	struct mbim_msghdr	hdr;
241
242
#define MBIM_ERROR_TIMEOUT_FRAGMENT		1
243
#define MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE	2
244
#define MBIM_ERROR_LENGTH_MISMATCH		3
245
#define MBIM_ERROR_DUPLICATED_TID		4
246
#define MBIM_ERROR_NOT_OPENED			5
247
#define MBIM_ERROR_UNKNOWN			6
248
#define MBIM_ERROR_CANCEL			7
249
#define MBIM_ERROR_MAX_TRANSFER			8
250
	uint32_t		err;
251
} __packed;
252
253
struct mbim_f2h_openclosedone {
254
	struct mbim_msghdr	hdr;
255
	int32_t			status;
256
} __packed;
257
258
struct mbim_f2h_cmddone {
259
	struct mbim_msghdr	hdr;
260
	struct mbim_fraghdr	frag;
261
	uint8_t			devid[MBIM_UUID_LEN];
262
	uint32_t		cid;		/* command id */
263
	int32_t			status;
264
	uint32_t		infolen;
265
	uint8_t			info[];
266
} __packed;
267
268
/*
269
 * Messages and commands for MBIM_UUID_BASIC_CONNECT
270
 */
271
#define MBIM_CID_DEVICE_CAPS				1
272
#define MBIM_CID_SUBSCRIBER_READY_STATUS		2
273
#define MBIM_CID_RADIO_STATE				3
274
#define MBIM_CID_PIN					4
275
#define MBIM_CID_PIN_LIST				5
276
#define MBIM_CID_HOME_PROVIDER				6
277
#define MBIM_CID_PREFERRED_PROVIDERS			7
278
#define MBIM_CID_VISIBLE_PROVIDERS			8
279
#define MBIM_CID_REGISTER_STATE				9
280
#define MBIM_CID_PACKET_SERVICE				10
281
#define MBIM_CID_SIGNAL_STATE				11
282
#define MBIM_CID_CONNECT				12
283
#define MBIM_CID_PROVISIONED_CONTEXTS			13
284
#define MBIM_CID_SERVICE_ACTIVATION			14
285
#define MBIM_CID_IP_CONFIGURATION			15
286
#define MBIM_CID_DEVICE_SERVICES			16
287
#define MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST		19
288
#define MBIM_CID_PACKET_STATISTICS			20
289
#define MBIM_CID_NETWORK_IDLE_HINT			21
290
#define MBIM_CID_EMERGENCY_MODE				22
291
#define MBIM_CID_IP_PACKET_FILTERS			23
292
#define MBIM_CID_MULTICARRIER_PROVIDERS			24
293
294
struct mbim_cid_subscriber_ready_info {
295
#define MBIM_SIMSTATE_NOTINITIALIZED		0
296
#define MBIM_SIMSTATE_INITIALIZED		1
297
#define MBIM_SIMSTATE_NOTINSERTED		2
298
#define MBIM_SIMSTATE_BADSIM			3
299
#define MBIM_SIMSTATE_FAILURE			4
300
#define MBIM_SIMSTATE_NOTACTIVATED		5
301
#define MBIM_SIMSTATE_LOCKED			6
302
	uint32_t	ready;
303
304
	uint32_t	sid_offs;
305
	uint32_t	sid_size;
306
307
	uint32_t	icc_offs;
308
	uint32_t	icc_size;
309
310
#define MBIM_SIMUNIQEID_NONE			0
311
#define MBIM_SIMUNIQEID_PROTECT			1
312
	uint32_t	info;
313
314
	uint32_t	no_pn;
315
	struct {
316
		uint32_t	offs;
317
		uint32_t	size;
318
	}
319
			pn[];
320
} __packed;
321
322
struct mbim_cid_radio_state {
323
#define MBIM_RADIO_STATE_OFF			0
324
#define MBIM_RADIO_STATE_ON			1
325
	uint32_t	state;
326
} __packed;
327
328
struct mbim_cid_radio_state_info {
329
	uint32_t	hw_state;
330
	uint32_t	sw_state;
331
} __packed;
332
333
struct mbim_cid_pin {
334
#define MBIM_PIN_TYPE_NONE			0
335
#define MBIM_PIN_TYPE_CUSTOM			1
336
#define MBIM_PIN_TYPE_PIN1			2
337
#define MBIM_PIN_TYPE_PIN2			3
338
#define MBIM_PIN_TYPE_DEV_SIM_PIN		4
339
#define MBIM_PIN_TYPE_DEV_FIRST_SIM_PIN		5
340
#define MBIM_PIN_TYPE_NETWORK_PIN		6
341
#define MBIM_PIN_TYPE_NETWORK_SUBSET_PIN	7
342
#define MBIM_PIN_TYPE_SERVICE_PROVIDER_PIN	8
343
#define MBIM_PIN_TYPE_CORPORATE_PIN		9
344
#define MBIM_PIN_TYPE_SUBSIDY_LOCK		10
345
#define MBIM_PIN_TYPE_PUK1			11
346
#define MBIM_PIN_TYPE_PUK2			12
347
#define MBIM_PIN_TYPE_DEV_FIRST_SIM_PUK		13
348
#define MBIM_PIN_TYPE_NETWORK_PUK		14
349
#define MBIM_PIN_TYPE_NETWORK_SUBSET_PUK	15
350
#define MBIM_PIN_TYPE_SERVICE_PROVIDER_PUK	16
351
#define MBIM_PIN_TYPE_CORPORATE_PUK		17
352
	uint32_t	type;
353
354
#define MBIM_PIN_OP_ENTER			0
355
#define MBIM_PIN_OP_ENABLE			1
356
#define MBIM_PIN_OP_DISABLE			2
357
#define MBIM_PIN_OP_CHANGE			3
358
	uint32_t	op;
359
	uint32_t	pin_offs;
360
	uint32_t	pin_size;
361
	uint32_t	newpin_offs;
362
	uint32_t	newpin_size;
363
#define MBIM_PIN_MAXLEN	32
364
	uint8_t		data[2 * MBIM_PIN_MAXLEN];
365
} __packed;
366
367
struct mbim_cid_pin_info {
368
	uint32_t	type;
369
370
#define MBIM_PIN_STATE_UNLOCKED			0
371
#define MBIM_PIN_STATE_LOCKED			1
372
	uint32_t	state;
373
	uint32_t	remaining_attempts;
374
} __packed;
375
376
struct mbim_cid_pin_list_info {
377
	struct mbim_pin_desc {
378
379
#define MBIM_PINMODE_NOTSUPPORTED		0
380
#define MBIM_PINMODE_ENABLED			1
381
#define MBIM_PINMODE_DISABLED			2
382
		uint32_t	mode;
383
384
#define MBIM_PINFORMAT_UNKNOWN			0
385
#define MBIM_PINFORMAT_NUMERIC			1
386
#define MBIM_PINFORMAT_ALPHANUMERIC		2
387
		uint32_t	format;
388
389
		uint32_t	minlen;
390
		uint32_t	maxlen;
391
	}
392
		pin1,
393
		pin2,
394
		dev_sim_pin,
395
		first_dev_sim_pin,
396
		net_pin,
397
		net_sub_pin,
398
		svp_pin,
399
		corp_pin,
400
		subsidy_lock,
401
		custom;
402
} __packed;
403
404
struct mbim_cid_device_caps {
405
#define MBIM_DEVTYPE_UNKNOWN			0
406
#define MBIM_DEVTYPE_EMBEDDED			1
407
#define MBIM_DEVTYPE_REMOVABLE			2
408
#define MBIM_DEVTYPE_REMOTE			3
409
	uint32_t	devtype;
410
411
	uint32_t	cellclass;	/* values: MBIM_CELLULAR_CLASS */
412
	uint32_t	voiceclass;
413
	uint32_t	simclass;
414
	uint32_t	dataclass;	/* values: MBIM_DATA_CLASS */
415
	uint32_t	smscaps;
416
	uint32_t	cntrlcaps;
417
	uint32_t	max_sessions;
418
419
	uint32_t	custdataclass_offs;
420
	uint32_t	custdataclass_size;
421
422
	uint32_t	devid_offs;
423
	uint32_t	devid_size;
424
425
	uint32_t	fwinfo_offs;
426
	uint32_t	fwinfo_size;
427
428
	uint32_t	hwinfo_offs;
429
	uint32_t	hwinfo_size;
430
431
	uint32_t	data[];
432
} __packed;
433
434
struct mbim_cid_registration_state {
435
	uint32_t	provid_offs;
436
	uint32_t	provid_size;
437
438
#define MBIM_REGACTION_AUTOMATIC		0
439
#define MBIM_REGACTION_MANUAL			1
440
	uint32_t	regaction;
441
	uint32_t	data_class;
442
443
	uint32_t	data[];
444
} __packed;
445
446
struct mbim_cid_registration_state_info {
447
	uint32_t	nwerror;
448
449
	uint32_t	regstate;	/* values: MBIM_REGISTER_STATE */
450
451
#define MBIM_REGMODE_UNKNOWN			0
452
#define MBIM_REGMODE_AUTOMATIC			1
453
#define MBIM_REGMODE_MANUAL			2
454
	uint32_t	regmode;
455
456
	uint32_t	availclasses;	/* values: MBIM_DATA_CLASS */
457
	uint32_t	curcellclass;	/* values: MBIM_CELLULAR_CLASS */
458
459
	uint32_t	provid_offs;
460
	uint32_t	provid_size;
461
462
	uint32_t	provname_offs;
463
	uint32_t	provname_size;
464
465
	uint32_t	roamingtxt_offs;
466
	uint32_t	roamingtxt_size;
467
468
#define MBIM_REGFLAGS_NONE			0
469
#define MBIM_REGFLAGS_MANUAL_NOT_AVAILABLE	1
470
#define MBIM_REGFLAGS_PACKETSERVICE_AUTOATTACH	2
471
	uint32_t	regflag;
472
473
	uint32_t	data[];
474
} __packed;
475
476
struct mbim_cid_packet_service {
477
#define MBIM_PKTSERVICE_ACTION_ATTACH		0
478
#define MBIM_PKTSERVICE_ACTION_DETACH		1
479
	uint32_t	action;
480
} __packed;
481
482
struct mbim_cid_packet_service_info {
483
	uint32_t	nwerror;
484
485
#define MBIM_PKTSERVICE_STATE_UNKNOWN		0
486
#define MBIM_PKTSERVICE_STATE_ATTACHING		1
487
#define MBIM_PKTSERVICE_STATE_ATTACHED		2
488
#define MBIM_PKTSERVICE_STATE_DETACHING		3
489
#define MBIM_PKTSERVICE_STATE_DETACHED		4
490
	uint32_t	state;
491
492
	uint32_t	highest_dataclass;
493
	uint64_t	uplink_speed;
494
	uint64_t	downlink_speed;
495
} __packed;
496
497
struct mbim_cid_signal_state {
498
	uint32_t	rssi;
499
	uint32_t	err_rate;
500
	uint32_t	ss_intvl;
501
	uint32_t	rssi_thr;
502
	uint32_t	err_thr;
503
} __packed;
504
505
struct mbim_cid_connect {
506
	uint32_t	sessionid;
507
508
#define MBIM_CONNECT_DEACTIVATE		0
509
#define MBIM_CONNECT_ACTIVATE		1
510
	uint32_t	command;
511
512
#define MBIM_ACCESS_MAXLEN		200
513
	uint32_t	access_offs;
514
	uint32_t	access_size;
515
516
#define MBIM_USER_MAXLEN		510
517
	uint32_t	user_offs;
518
	uint32_t	user_size;
519
520
#define MBIM_PASSWD_MAXLEN		510
521
	uint32_t	passwd_offs;
522
	uint32_t	passwd_size;
523
524
#define MBIM_COMPRESSION_NONE		0
525
#define MBIM_COMPRESSION_ENABLE		1
526
	uint32_t	compression;
527
528
#define MBIM_AUTHPROT_NONE		0
529
#define MBIM_AUTHPROT_PAP		1
530
#define MBIM_AUTHPROT_CHAP		2
531
#define MBIM_AUTHPROT_MSCHAP		3
532
	uint32_t	authprot;
533
534
#define MBIM_CONTEXT_IPTYPE_DEFAULT	0
535
#define MBIM_CONTEXT_IPTYPE_IPV4	1
536
#define MBIM_CONTEXT_IPTYPE_IPV6	2
537
#define MBIM_CONTEXT_IPTYPE_IPV4V6	3
538
#define MBIM_CONTEXT_IPTYPE_IPV4ANDV6	4
539
	uint32_t	iptype;
540
541
	uint8_t		context[MBIM_UUID_LEN];
542
543
	uint8_t		data[MBIM_ACCESS_MAXLEN + MBIM_USER_MAXLEN +
544
			     MBIM_PASSWD_MAXLEN];
545
546
} __packed;
547
548
struct mbim_cid_connect_info {
549
	uint32_t	sessionid;
550
551
#define MBIM_ACTIVATION_STATE_UNKNOWN		0
552
#define MBIM_ACTIVATION_STATE_ACTIVATED		1
553
#define MBIM_ACTIVATION_STATE_ACTIVATING	2
554
#define MBIM_ACTIVATION_STATE_DEACTIVATED	3
555
#define MBIM_ACTIVATION_STATE_DEACTIVATING	4
556
	uint32_t	activation;
557
558
	uint32_t	voice;
559
	uint32_t	iptype;
560
	uint8_t		context[MBIM_UUID_LEN];
561
	uint32_t	nwerror;
562
} __packed;
563
564
struct mbim_cid_ipv4_element {
565
	uint32_t	prefixlen;
566
	uint32_t	addr;
567
} __packed;
568
569
struct mbim_cid_ipv6_element {
570
	uint32_t	prefixlen;
571
	uint8_t		addr[16];
572
} __packed;
573
574
struct mbim_cid_ip_configuration_info {
575
	uint32_t	sessionid;
576
577
#define MBIM_IPCONF_HAS_ADDRINFO	0x0001
578
#define MBIM_IPCONF_HAS_GWINFO		0x0002
579
#define MBIM_IPCONF_HAS_DNSINFO		0x0004
580
#define MBIM_IPCONF_HAS_MTUINFO		0x0008
581
	uint32_t	ipv4_available;
582
	uint32_t	ipv6_available;
583
584
	uint32_t	ipv4_naddr;
585
	uint32_t	ipv4_addroffs;
586
	uint32_t	ipv6_naddr;
587
	uint32_t	ipv6_addroffs;
588
589
	uint32_t	ipv4_gwoffs;
590
	uint32_t	ipv6_gwoffs;
591
592
	uint32_t	ipv4_ndnssrv;
593
	uint32_t	ipv4_dnssrvoffs;
594
	uint32_t	ipv6_ndnssrv;
595
	uint32_t	ipv6_dnssrvoffs;
596
597
	uint32_t	ipv4_mtu;
598
	uint32_t	ipv6_mtu;
599
600
	uint32_t	data[];
601
} __packed;
602
603
struct mbim_cid_packet_statistics_info {
604
	uint32_t	in_discards;
605
	uint32_t	in_errors;
606
	uint64_t	in_octets;
607
	uint64_t	in_packets;
608
	uint64_t	out_octets;
609
	uint64_t	out_packets;
610
	uint32_t	out_errors;
611
	uint32_t	out_discards;
612
} __packed;
613
614
615
#ifdef _KERNEL
616
617
struct mbim_descriptor {
618
	uByte	bLength;
619
	uByte	bDescriptorType;
620
	uByte	bDescriptorSubtype;
621
#define MBIM_VER_MAJOR(v)	(((v) >> 8) & 0x0f)
622
#define MBIM_VER_MINOR(v)	((v) & 0x0f)
623
	uWord	bcdMBIMVersion;
624
	uWord	wMaxControlMessage;
625
	uByte	bNumberFilters;
626
	uByte	bMaxFilterSize;
627
	uWord	wMaxSegmentSize;
628
	uByte	bmNetworkCapabilities;
629
} __packed;
630
631
/*
632
 * NCM Parameters
633
 */
634
#define NCM_GET_NTB_PARAMETERS	0x80
635
636
struct ncm_ntb_parameters {
637
	uWord	wLength;
638
	uWord	bmNtbFormatsSupported;
639
#define NCM_FORMAT_NTB16	0x0001
640
#define NCM_FORMAT_NTB32	0x0002
641
	uDWord	dwNtbInMaxSize;
642
	uWord	wNdpInDivisor;
643
	uWord	wNdpInPayloadRemainder;
644
	uWord	wNdpInAlignment;
645
	uWord	wReserved1;
646
	uDWord	dwNtbOutMaxSize;
647
	uWord	wNdpOutDivisor;
648
	uWord	wNdpOutPayloadRemainder;
649
	uWord	wNdpOutAlignment;
650
	uWord	wNtbOutMaxDatagrams;
651
} __packed;
652
653
/*
654
 * NCM Encoding
655
 */
656
#define MBIM_HDR16_LEN	\
657
	(sizeof(struct ncm_header16) + sizeof(struct ncm_pointer16))
658
#define MBIM_HDR32_LEN	\
659
	(sizeof(struct ncm_header32) + sizeof(struct ncm_pointer32))
660
661
struct ncm_header16 {
662
#define NCM_HDR16_SIG		0x484d434e
663
	uDWord	dwSignature;
664
	uWord	wHeaderLength;
665
	uWord	wSequence;
666
	uWord	wBlockLength;
667
	uWord	wNdpIndex;
668
} __packed;
669
670
struct ncm_header32 {
671
#define NCM_HDR32_SIG		0x686d636e
672
	uDWord	dwSignature;
673
	uWord	wHeaderLength;
674
	uWord	wSequence;
675
	uDWord	dwBlockLength;
676
	uDWord	dwNdpIndex;
677
} __packed;
678
679
680
#define MBIM_NCM_NTH_SIDSHIFT	24
681
#define MBIM_NCM_NTH_GETSID(s)	(((s) > MBIM_NCM_NTH_SIDSHIFT) & 0xff)
682
683
struct ncm_pointer16_dgram {
684
	uWord	wDatagramIndex;
685
	uWord	wDatagramLen;
686
} __packed;
687
688
struct ncm_pointer16 {
689
#define MBIM_NCM_NTH16_IPS	 0x00535049
690
#define MBIM_NCM_NTH16_ISISG(s) (((s) & 0x00ffffff) == MBIM_NCM_NTH16_IPS)
691
#define MBIM_NCM_NTH16_SIG(s)	\
692
		((((s) & 0xff) << MBIM_NCM_NTH_SIDSHIFT) | MBIM_NCM_NTH16_IPS)
693
	uDWord	dwSignature;
694
	uWord	wLength;
695
	uWord	wNextNdpIndex;
696
697
	/* Minimum is two datagrams, but can be more */
698
	struct ncm_pointer16_dgram dgram[2];
699
} __packed;
700
701
struct ncm_pointer32_dgram {
702
	uDWord	dwDatagramIndex;
703
	uDWord	dwDatagramLen;
704
} __packed;
705
706
struct ncm_pointer32 {
707
#define MBIM_NCM_NTH32_IPS	0x00737069
708
#define MBIM_NCM_NTH32_ISISG(s)	\
709
		(((s) & 0x00ffffff) == MBIM_NCM_NTH32_IPS)
710
#define MBIM_NCM_NTH32_SIG(s)		\
711
		((((s) & 0xff) << MBIM_NCM_NTH_SIDSHIFT) | MBIM_NCM_NTH32_IPS)
712
	uDWord	dwSignature;
713
	uWord	wLength;
714
	uWord	wReserved6;
715
	uDWord	dwNextNdpIndex;
716
	uDWord	dwReserved12;
717
718
	/* Minimum is two datagrams, but can be more */
719
	struct ncm_pointer32_dgram dgram[2];
720
} __packed;
721
722
#endif /* _KERNEL */
723
724
#endif /* _MBIM_H_ */
(-)b/sys/modules/usb/Makefile (-1 / +1 lines)
Lines 49-55 SUBDIR += ${_rum} ${_run} ${_runfw} ${_uath} upgt usie ural ${_zyd} ${_urtw} Link Here
49
SUBDIR += atp cfumass uhid uhid_snes ukbd ums udbp uep wmt wsp ugold uled \
49
SUBDIR += atp cfumass uhid uhid_snes ukbd ums udbp uep wmt wsp ugold uled \
50
	  usbhid
50
	  usbhid
51
SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
51
SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
52
	  umct umcs umodem umoscom uplcom uslcom uvisor uvscom
52
	  umb umct umcs umodem umoscom uplcom uslcom uvisor uvscom
53
SUBDIR += i2ctinyusb
53
SUBDIR += i2ctinyusb
54
SUBDIR += cp2112
54
SUBDIR += cp2112
55
SUBDIR += udl
55
SUBDIR += udl
(-)b/sys/modules/usb/umb/Makefile (+35 lines)
Added Link Here
1
#
2
#
3
# Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions
7
# are met:
8
# 1. Redistributions of source code must retain the above copyright
9
#    notice, this list of conditions and the following disclaimer.
10
# 2. Redistributions in binary form must reproduce the above copyright
11
#    notice, this list of conditions and the following disclaimer in the
12
#    documentation and/or other materials provided with the distribution.
13
#
14
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
# SUCH DAMAGE.
25
#
26
27
S=     ${SRCTOP}/sys
28
29
.PATH: $S/dev/usb/net
30
31
KMOD=	umb
32
SRCS=	opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \
33
	if_umb.c
34
35
.include <bsd.kmod.mk>
(-)b/sys/net/if_media.c (+11 lines)
Lines 398-403 static const struct ifmedia_description ifm_subtype_atm_descriptions[] = Link Here
398
static const struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
398
static const struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
399
    IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
399
    IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
400
400
401
static const struct ifmedia_description ifm_subtype_mbim_descriptions[] =
402
    IFM_SUBTYPE_MBIM_DESCRIPTIONS;
403
404
static const struct ifmedia_description ifm_subtype_mbim_option_descriptions[] =
405
    IFM_SUBTYPE_MBIM_OPTION_DESCRIPTIONS;
406
401
static const struct ifmedia_description ifm_subtype_shared_descriptions[] =
407
static const struct ifmedia_description ifm_subtype_shared_descriptions[] =
402
    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
408
    IFM_SUBTYPE_SHARED_DESCRIPTIONS;
403
409
Lines 427-432 static const struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { Link Here
427
	  &ifm_subtype_atm_option_descriptions[0],
433
	  &ifm_subtype_atm_option_descriptions[0],
428
	  NULL,
434
	  NULL,
429
	},
435
	},
436
	{
437
	  &ifm_subtype_mbim_descriptions[0],
438
	  &ifm_subtype_mbim_option_descriptions[0],
439
	  NULL,
440
	},
430
};
441
};
431
442
432
/*
443
/*
(-)b/sys/net/if_media.h (+40 lines)
Lines 338-343 uint64_t ifmedia_baudrate(int); Link Here
338
#define	IFM_ATM_NOSCRAMB	0x00000200	/* no scrambling */
338
#define	IFM_ATM_NOSCRAMB	0x00000200	/* no scrambling */
339
#define	IFM_ATM_UNASSIGNED	0x00000400	/* unassigned cells */
339
#define	IFM_ATM_UNASSIGNED	0x00000400	/* unassigned cells */
340
340
341
/*
342
 * MBIM
343
 */
344
#define	IFM_MBIM	0x00000100
345
#define	IFM_MBIM_UNKNOWN	3
346
#define	IFM_MBIM_GPRS		4
347
#define	IFM_MBIM_EDGE		5
348
#define	IFM_MBIM_UMTS		6
349
#define	IFM_MBIM_HSDPA		7
350
#define	IFM_MBIM_HSUPA		8
351
#define	IFM_MBIM_LTE		9
352
341
/*
353
/*
342
 * Shared media sub-types
354
 * Shared media sub-types
343
 */
355
 */
Lines 425-430 struct ifmedia_description { Link Here
425
	{ IFM_ETHER,		"Ethernet" },				\
437
	{ IFM_ETHER,		"Ethernet" },				\
426
	{ IFM_IEEE80211,	"IEEE 802.11 Wireless Ethernet" },	\
438
	{ IFM_IEEE80211,	"IEEE 802.11 Wireless Ethernet" },	\
427
	{ IFM_ATM,		"ATM" },				\
439
	{ IFM_ATM,		"ATM" },				\
440
	{ IFM_MBIM,		"MBIM" },				\
428
	{ 0, NULL },							\
441
	{ 0, NULL },							\
429
}
442
}
430
443
Lines 728-733 struct ifmedia_description { Link Here
728
	{ 0, NULL },							\
741
	{ 0, NULL },							\
729
}
742
}
730
743
744
#define	IFM_SUBTYPE_MBIM_DESCRIPTIONS {					\
745
	{ IFM_MBIM_UNKNOWN,	"Unknown" },				\
746
	{ IFM_MBIM_GPRS,	"GPRS" },				\
747
	{ IFM_MBIM_EDGE,	"EDGE" },				\
748
	{ IFM_MBIM_UMTS,	"UMTS" },				\
749
	{ IFM_MBIM_HSDPA,	"HSDPA" },				\
750
	{ IFM_MBIM_HSUPA,	"HSUPA" },				\
751
	{ IFM_MBIM_LTE,		"LTE" },				\
752
}
753
754
#define	IFM_SUBTYPE_MBIM_ALIASES {					\
755
	{ IFM_MBIM_UNKNOWN,	"UNKNOWN" },				\
756
	{ IFM_MBIM_GPRS,	"2G" },					\
757
	{ IFM_MBIM_EDGE,	"2.5G" },				\
758
	{ IFM_MBIM_UMTS,	"3G" },					\
759
	{ IFM_MBIM_HSDPA,	"3G" },					\
760
	{ IFM_MBIM_HSUPA,	"3G" },					\
761
	{ IFM_MBIM_LTE,		"4G" },					\
762
	{ 0, NULL },							\
763
}
764
765
#define	IFM_SUBTYPE_MBIM_OPTION_DESCRIPTIONS {				\
766
	{ 0, NULL },							\
767
}
768
731
#define	IFM_SUBTYPE_SHARED_DESCRIPTIONS {				\
769
#define	IFM_SUBTYPE_SHARED_DESCRIPTIONS {				\
732
	{ IFM_AUTO,	"autoselect" },					\
770
	{ IFM_AUTO,	"autoselect" },					\
733
	{ IFM_MANUAL,	"manual" },					\
771
	{ IFM_MANUAL,	"manual" },					\
Lines 932-937 struct ifmedia_status_description { Link Here
932
	    { "no network", "active" } },				\
970
	    { "no network", "active" } },				\
933
	{ IFM_ATM,		IFM_AVALID,	IFM_ACTIVE,		\
971
	{ IFM_ATM,		IFM_AVALID,	IFM_ACTIVE,		\
934
	    { "no network", "active" } },				\
972
	    { "no network", "active" } },				\
973
	{ IFM_MBIM,		IFM_AVALID,	IFM_ACTIVE,		\
974
	    { "no network", "active" } },				\
935
	{ 0,			0,		0,			\
975
	{ 0,			0,		0,			\
936
	    { NULL, NULL } }						\
976
	    { NULL, NULL } }						\
937
}
977
}
(-)b/sys/net/if_types.h (+1 lines)
Lines 254-259 typedef enum { Link Here
254
	IFT_PFLOG	= 0xf6,		/* PF packet filter logging */
254
	IFT_PFLOG	= 0xf6,		/* PF packet filter logging */
255
	IFT_PFSYNC	= 0xf7,		/* PF packet filter synchronization */
255
	IFT_PFSYNC	= 0xf7,		/* PF packet filter synchronization */
256
	IFT_WIREGUARD	= 0xf8,		/* WireGuard tunnel */
256
	IFT_WIREGUARD	= 0xf8,		/* WireGuard tunnel */
257
	IFT_MBIM	= 0xf9		/* Mobile Broadband Interface Model */
257
} ifType;
258
} ifType;
258
259
259
/*
260
/*
(-)b/sys/sys/sockio.h (-1 / +4 lines)
Lines 147-150 Link Here
147
#define	SIOCSIFCAPNV	_IOW('i', 155, struct ifreq)	/* set IF features */
147
#define	SIOCSIFCAPNV	_IOW('i', 155, struct ifreq)	/* set IF features */
148
#define	SIOCGIFCAPNV	_IOWR('i', 156, struct ifreq)	/* get IF features */
148
#define	SIOCGIFCAPNV	_IOWR('i', 156, struct ifreq)	/* get IF features */
149
149
150
#define	SIOCGUMBINFO	_IOWR('i', 157, struct ifreq)	/* get MBIM info */
151
#define	SIOCSUMBPARAM	 _IOW('i', 158, struct ifreq)	/* set MBIM param */
152
#define	SIOCGUMBPARAM	_IOWR('i', 159, struct ifreq)	/* get MBIM param */
153
150
#endif /* !_SYS_SOCKIO_H_ */
154
#endif /* !_SYS_SOCKIO_H_ */
151
- 

Return to bug 263783