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 (+2920 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
static void	 umb_input(struct ifnet *, struct mbuf *);
180
static int	 umb_output(struct ifnet *, struct mbuf *,
181
		    const struct sockaddr *, struct route *);
182
static void	 umb_start(struct ifnet *);
183
static void	 umb_start_task(struct usb_proc_msg *);
184
#if 0
185
static void	 umb_watchdog(struct ifnet *);
186
#endif
187
static void	 umb_statechg_timeout(void *);
188
189
static int	 umb_mediachange(struct ifnet *);
190
static void	 umb_mediastatus(struct ifnet *, struct ifmediareq *);
191
192
static void	 umb_add_task(struct umb_softc *sc, usb_proc_callback_t,
193
		    struct usb_proc_msg *, struct usb_proc_msg *, int);
194
static void	 umb_newstate(struct umb_softc *, enum umb_state, int);
195
static void	 umb_state_task(struct usb_proc_msg *);
196
static void	 umb_up(struct umb_softc *);
197
static void	 umb_down(struct umb_softc *, int);
198
199
static void	 umb_get_response_task(struct usb_proc_msg *);
200
201
static void	 umb_decode_response(struct umb_softc *, void *, int);
202
static void	 umb_handle_indicate_status_msg(struct umb_softc *, void *,
203
		    int);
204
static void	 umb_handle_opendone_msg(struct umb_softc *, void *, int);
205
static void	 umb_handle_closedone_msg(struct umb_softc *, void *, int);
206
static int	 umb_decode_register_state(struct umb_softc *, void *, int);
207
static int	 umb_decode_devices_caps(struct umb_softc *, void *, int);
208
static int	 umb_decode_subscriber_status(struct umb_softc *, void *, int);
209
static int	 umb_decode_radio_state(struct umb_softc *, void *, int);
210
static int	 umb_decode_pin(struct umb_softc *, void *, int);
211
static int	 umb_decode_packet_service(struct umb_softc *, void *, int);
212
static int	 umb_decode_signal_state(struct umb_softc *, void *, int);
213
static int	 umb_decode_connect_info(struct umb_softc *, void *, int);
214
static int	 umb_decode_ip_configuration(struct umb_softc *, void *, int);
215
static void	 umb_rx(struct umb_softc *);
216
static usb_callback_t umb_rxeof;
217
static void	 umb_rxflush(struct umb_softc *);
218
static int	 umb_encap(struct umb_softc *, struct mbuf *, struct usb_xfer *);
219
static usb_callback_t umb_txeof;
220
static void	 umb_txflush(struct umb_softc *);
221
static void	 umb_decap(struct umb_softc *, struct usb_xfer *, int);
222
223
static usb_error_t	 umb_send_encap_command(struct umb_softc *, void *, int);
224
static int	 umb_get_encap_response(struct umb_softc *, void *, int *);
225
static void	 umb_ctrl_msg(struct umb_softc *, uint32_t, void *, int);
226
227
static void	 umb_open(struct umb_softc *);
228
static void	 umb_close(struct umb_softc *);
229
230
static int	 umb_setpin(struct umb_softc *, int, int, void *, int, void *,
231
		    int);
232
static void	 umb_setdataclass(struct umb_softc *);
233
static void	 umb_radio(struct umb_softc *, int);
234
static void	 umb_allocate_cid(struct umb_softc *);
235
static void	 umb_send_fcc_auth(struct umb_softc *);
236
static void	 umb_packet_service(struct umb_softc *, int);
237
static void	 umb_connect(struct umb_softc *);
238
static void	 umb_disconnect(struct umb_softc *);
239
static void	 umb_send_connect(struct umb_softc *, int);
240
241
static void	 umb_qry_ipconfig(struct umb_softc *);
242
static void	 umb_cmd(struct umb_softc *, int, int, const void *, int);
243
static void	 umb_cmd1(struct umb_softc *, int, int, const void *, int, uint8_t *);
244
static void	 umb_command_done(struct umb_softc *, void *, int);
245
static void	 umb_decode_cid(struct umb_softc *, uint32_t, void *, int);
246
static void	 umb_decode_qmi(struct umb_softc *, uint8_t *, int);
247
248
static usb_callback_t umb_intr;
249
250
static char	*umb_ntop(struct sockaddr *);
251
252
static const int umb_xfer_tout = USB_DEFAULT_TIMEOUT;
253
254
static uint8_t	 umb_uuid_basic_connect[] = MBIM_UUID_BASIC_CONNECT;
255
static uint8_t	 umb_uuid_context_internet[] = MBIM_UUID_CONTEXT_INTERNET;
256
static uint8_t	 umb_uuid_qmi_mbim[] = MBIM_UUID_QMI_MBIM;
257
static uint32_t	 umb_session_id = 0;
258
259
static const struct usb_config umb_config[UMB_N_TRANSFER] = {
260
	[UMB_INTR_RX] = {
261
		.type = UE_INTERRUPT,
262
		.endpoint = UE_ADDR_ANY,
263
		.direction = UE_DIR_IN,
264
		.if_index = 1,
265
		.callback = umb_intr,
266
		.bufsize = sizeof (struct usb_cdc_notification),
267
		.flags = {.pipe_bof = 1,.short_xfer_ok = 1},
268
		.usb_mode = USB_MODE_HOST,
269
	},
270
	[UMB_BULK_RX] = {
271
		.type = UE_BULK,
272
		.endpoint = UE_ADDR_ANY,
273
		.direction = UE_DIR_IN,
274
		.if_index = 0,
275
		.callback = umb_rxeof,
276
		.bufsize = 8 * 1024,
277
		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.ext_buffer = 1},
278
		.usb_mode = USB_MODE_HOST,
279
	},
280
	[UMB_BULK_TX] = {
281
		.type = UE_BULK,
282
		.endpoint = UE_ADDR_ANY,
283
		.direction = UE_DIR_OUT,
284
		.if_index = 0,
285
		.callback = umb_txeof,
286
		.bufsize = 8 * 1024,
287
		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1},
288
		.timeout = umb_xfer_tout,
289
		.usb_mode = USB_MODE_HOST,
290
	},
291
};
292
293
static device_method_t umb_methods[] = {
294
	/* USB interface */
295
	DEVMETHOD(usb_handle_request, umb_handle_request),
296
297
	/* Device interface */
298
	DEVMETHOD(device_probe, umb_probe),
299
	DEVMETHOD(device_attach, umb_attach),
300
	DEVMETHOD(device_detach, umb_detach),
301
	DEVMETHOD(device_suspend, umb_suspend),
302
	DEVMETHOD(device_resume, umb_resume),
303
304
	DEVMETHOD_END
305
};
306
307
static driver_t umb_driver = {
308
	.name = "umb",
309
	.methods = umb_methods,
310
	.size = sizeof (struct umb_softc),
311
};
312
313
MALLOC_DEFINE(M_USB_UMB, "USB UMB", "USB MBIM driver");
314
315
const int umb_delay = 4000;
316
317
/*
318
 * These devices require an "FCC Authentication" command.
319
 */
320
#ifndef USB_VENDOR_SIERRA
321
# define USB_VENDOR_SIERRA	0x1199
322
#endif
323
#ifndef USB_PRODUCT_SIERRA_EM7455
324
# define USB_PRODUCT_SIERRA_EM7455	0x9079
325
#endif
326
const struct usb_device_id umb_fccauth_devs[] = {
327
	{
328
		.match_flag_vendor = 1,
329
		.match_flag_product = 1,
330
		.idVendor = USB_VENDOR_SIERRA,
331
		.idProduct = USB_PRODUCT_SIERRA_EM7455
332
	}
333
};
334
335
static const uint8_t umb_qmi_alloc_cid[] = {
336
	0x01,
337
	0x0f, 0x00,		/* len */
338
	0x00,			/* QMUX flags */
339
	0x00,			/* service "ctl" */
340
	0x00,			/* CID */
341
	0x00,			/* QMI flags */
342
	0x01,			/* transaction */
343
	0x22, 0x00,		/* msg "Allocate CID" */
344
	0x04, 0x00,		/* TLV len */
345
	0x01, 0x01, 0x00, 0x02	/* TLV */
346
};
347
348
static const uint8_t umb_qmi_fcc_auth[] = {
349
	0x01,
350
	0x0c, 0x00,		/* len */
351
	0x00,			/* QMUX flags */
352
	0x02,			/* service "dms" */
353
#define UMB_QMI_CID_OFFS	5
354
	0x00,			/* CID (filled in later) */
355
	0x00,			/* QMI flags */
356
	0x01, 0x00,		/* transaction */
357
	0x5f, 0x55,		/* msg "Send FCC Authentication" */
358
	0x00, 0x00		/* TLV len */
359
};
360
361
static int
362
umb_probe(device_t dev)
363
{
364
	struct usb_attach_arg *uaa = device_get_ivars(dev);
365
	usb_interface_descriptor_t *id;
366
367
	if (uaa->usb_mode != USB_MODE_HOST)
368
		return (ENXIO);
369
	if ((id = usbd_get_interface_descriptor(uaa->iface)) == NULL)
370
		return (ENXIO);
371
372
	/*
373
	 * If this function implements NCM, check if alternate setting
374
	 * 1 implements MBIM.
375
	 */
376
	if (id->bInterfaceClass == UICLASS_CDC &&
377
	    id->bInterfaceSubClass ==
378
	    UISUBCLASS_NETWORK_CONTROL_MODEL) {
379
		id = usbd_get_interface_descriptor(
380
				usbd_get_iface(uaa->device,
381
					uaa->info.bIfaceIndex + 1));
382
		if (id == NULL || id->bAlternateSetting != 1)
383
			return (ENXIO);
384
	}
385
386
#ifndef UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL
387
# define UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL 14
388
#endif
389
	if (id->bInterfaceClass == UICLASS_CDC &&
390
	    id->bInterfaceSubClass ==
391
	    UISUBCLASS_MOBILE_BROADBAND_INTERFACE_MODEL &&
392
	    id->bInterfaceProtocol == 0)
393
		return (BUS_PROBE_SPECIFIC);
394
395
	return (ENXIO);
396
}
397
398
static int
399
umb_attach(device_t dev)
400
{
401
	struct umb_softc *sc = device_get_softc(dev);
402
	struct usb_attach_arg *uaa = device_get_ivars(dev);
403
	struct usb_config config[UMB_N_TRANSFER];
404
	int	 v;
405
	const struct usb_cdc_union_descriptor *ud;
406
	const struct mbim_descriptor *md;
407
	int	 i;
408
	usb_interface_descriptor_t *id;
409
	struct usb_interface *iface;
410
	int	 data_ifaceno = -1;
411
	usb_error_t error;
412
413
	sc->sc_dev = dev;
414
	sc->sc_udev = uaa->device;
415
416
	memcpy(config, umb_config, sizeof (config));
417
418
	device_set_usb_desc(dev);
419
420
	sc->sc_ctrl_ifaceno = uaa->info.bIfaceNum;
421
422
	mtx_init(&sc->sc_mutex, device_get_nameunit(dev), NULL, MTX_DEF);
423
424
	/*
425
	 * Some MBIM hardware does not provide the mandatory CDC Union
426
	 * Descriptor, so we also look at matching Interface
427
	 * Association Descriptors to find out the MBIM Data Interface
428
	 * number.
429
	 */
430
	sc->sc_ver_maj = sc->sc_ver_min = -1;
431
	sc->sc_maxpktlen = MBIM_MAXSEGSZ_MINVAL;
432
	id = usbd_get_interface_descriptor(uaa->iface);
433
434
	ud = usbd_find_descriptor(sc->sc_udev, id, uaa->info.bIfaceIndex,
435
			UDESC_CS_INTERFACE, 0xff, UDESCSUB_CDC_UNION, 0xff);
436
	if (ud != NULL) {
437
		data_ifaceno = ud->bSlaveInterface[0];
438
	}
439
440
	md = usbd_find_descriptor(sc->sc_udev, id, uaa->info.bIfaceIndex,
441
			UDESC_CS_INTERFACE, 0xff, UDESCSUB_MBIM, 0xff);
442
	if (md != NULL) {
443
		v = UGETW(md->bcdMBIMVersion);
444
		sc->sc_ver_maj = MBIM_VER_MAJOR(v);
445
		sc->sc_ver_min = MBIM_VER_MINOR(v);
446
		sc->sc_ctrl_len = UGETW(md->wMaxControlMessage);
447
		/* Never trust a USB device! Could try to exploit us */
448
		if (sc->sc_ctrl_len < MBIM_CTRLMSG_MINLEN ||
449
				sc->sc_ctrl_len > MBIM_CTRLMSG_MAXLEN) {
450
			DPRINTF("control message len %d out of "
451
					"bounds [%d .. %d]\n",
452
					sc->sc_ctrl_len, MBIM_CTRLMSG_MINLEN,
453
					MBIM_CTRLMSG_MAXLEN);
454
			/* continue anyway */
455
		}
456
		sc->sc_maxpktlen = UGETW(md->wMaxSegmentSize);
457
		DPRINTFN(2, "ctrl_len=%d, maxpktlen=%d, cap=0x%x\n",
458
				sc->sc_ctrl_len, sc->sc_maxpktlen,
459
				md->bmNetworkCapabilities);
460
	}
461
	if (sc->sc_ver_maj < 0) {
462
		device_printf(dev, "error: missing MBIM descriptor\n");
463
		goto fail;
464
	}
465
466
	device_printf(dev, "version %d.%d\n", sc->sc_ver_maj,
467
	    sc->sc_ver_min);
468
469
	if (usbd_lookup_id_by_uaa(umb_fccauth_devs, sizeof (umb_fccauth_devs),
470
				  uaa)) {
471
		sc->sc_flags |= UMBFLG_FCC_AUTH_REQUIRED;
472
		sc->sc_cid = -1;
473
	}
474
475
	for (i = 0; i < sc->sc_udev->ifaces_max; i++) {
476
		iface = usbd_get_iface(sc->sc_udev, i);
477
		id = usbd_get_interface_descriptor(iface);
478
		if (id == NULL)
479
			break;
480
481
		if (id->bInterfaceNumber == data_ifaceno) {
482
			sc->sc_data_iface = iface;
483
			sc->sc_ifaces_index[0] = i;
484
			sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
485
			break;
486
		}
487
	}
488
	if (sc->sc_data_iface == NULL) {
489
		device_printf(dev, "error: no data interface found\n");
490
		goto fail;
491
	}
492
493
	/*
494
	 * If this is a combined NCM/MBIM function, switch to
495
	 * alternate setting one to enable MBIM.
496
	 */
497
	id = usbd_get_interface_descriptor(uaa->iface);
498
	if (id != NULL && id->bInterfaceClass == UICLASS_CDC &&
499
	    id->bInterfaceSubClass == UISUBCLASS_NETWORK_CONTROL_MODEL) {
500
		device_printf(sc->sc_dev, "combined NCM/MBIM\n");
501
		error = usbd_req_set_alt_interface_no(sc->sc_udev,
502
				NULL, uaa->info.bIfaceIndex, 1);
503
		if (error != USB_ERR_NORMAL_COMPLETION) {
504
			device_printf(dev, "error: Could not switch to"
505
					   " alternate setting for MBIM\n");
506
			goto fail;
507
		}
508
		sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex + 1;
509
	}
510
511
	if (usb_proc_create(&sc->sc_taskqueue, &sc->sc_mutex,
512
				device_get_nameunit(sc->sc_dev),
513
				USB_PRI_MED) != 0)
514
		goto fail;
515
516
	DPRINTFN(2, "ctrl-ifno#%d: data-ifno#%d\n", sc->sc_ctrl_ifaceno,
517
	    data_ifaceno);
518
519
	usb_callout_init_mtx(&sc->sc_statechg_timer, &sc->sc_mutex, 0);
520
521
	umb_ncm_setup(sc, config);
522
	DPRINTFN(2, "%s: rx/tx size %d/%d\n", DEVNAM(sc),
523
			sc->sc_rx_bufsz, sc->sc_tx_bufsz);
524
525
	sc->sc_rx_buf = malloc(sc->sc_rx_bufsz, M_DEVBUF, M_WAITOK);
526
	sc->sc_tx_buf = malloc(sc->sc_tx_bufsz, M_DEVBUF, M_WAITOK);
527
528
	for (i = 0; i != 32; i++) {
529
		error = usbd_set_alt_interface_index(sc->sc_udev,
530
				sc->sc_ifaces_index[0], i);
531
		if (error)
532
			break;
533
534
		error = usbd_transfer_setup(sc->sc_udev, sc->sc_ifaces_index,
535
				sc->sc_xfer, config, UMB_N_TRANSFER,
536
				sc, &sc->sc_mutex);
537
		if (error == USB_ERR_NORMAL_COMPLETION)
538
			break;
539
	}
540
	if (error || (i == 32)) {
541
		device_printf(sc->sc_dev, "error: failed to setup xfers\n");
542
		goto fail;
543
	}
544
545
	sc->sc_resp_buf = malloc(sc->sc_ctrl_len, M_DEVBUF, M_WAITOK);
546
	sc->sc_ctrl_msg = malloc(sc->sc_ctrl_len, M_DEVBUF, M_WAITOK);
547
548
	sc->sc_info.regstate = MBIM_REGSTATE_UNKNOWN;
549
	sc->sc_info.pin_attempts_left = UMB_VALUE_UNKNOWN;
550
	sc->sc_info.rssi = UMB_VALUE_UNKNOWN;
551
	sc->sc_info.ber = UMB_VALUE_UNKNOWN;
552
553
	/* defer attaching the interface */
554
	mtx_lock(&sc->sc_mutex);
555
	umb_add_task(sc, umb_attach_task,
556
			&sc->sc_proc_attach_task[0].hdr,
557
			&sc->sc_proc_attach_task[1].hdr, 0);
558
	mtx_unlock(&sc->sc_mutex);
559
560
	return (0);
561
562
fail:
563
	umb_detach(sc->sc_dev);
564
	return (ENXIO);
565
}
566
567
static void
568
umb_attach_task(struct usb_proc_msg *msg)
569
{
570
	struct umb_task *task = (struct umb_task *)msg;
571
	struct umb_softc *sc = task->sc;
572
	struct ifnet *ifp;
573
574
	mtx_unlock(&sc->sc_mutex);
575
576
	CURVNET_SET_QUIET(vnet0);
577
578
	/* initialize the interface */
579
	sc->sc_if = ifp = if_alloc(IFT_MBIM);
580
	if_initname(ifp, "umb", device_get_unit(sc->sc_dev));
581
582
	ifp->if_softc = sc;
583
	ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_POINTOPOINT;
584
	ifp->if_ioctl = umb_ioctl;
585
	ifp->if_input = umb_input;
586
	ifp->if_output = umb_output;
587
	ifp->if_start = umb_start;
588
	ifp->if_init = umb_init;
589
590
#if 0
591
	ifp->if_watchdog = umb_watchdog;
592
#endif
593
	ifp->if_link_state = LINK_STATE_DOWN;
594
	ifmedia_init(&sc->sc_im, 0, umb_mediachange, umb_mediastatus);
595
	ifmedia_add(&sc->sc_im, IFM_NONE | IFM_AUTO, 0, NULL);
596
597
	ifp->if_addrlen = 0;
598
	ifp->if_hdrlen = sizeof (struct ncm_header16) +
599
	    sizeof (struct ncm_pointer16);
600
	/* XXX hard-coded atm */
601
	ifp->if_mtu = MIN(2048, sc->sc_maxpktlen);
602
	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
603
	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
604
	IFQ_SET_READY(&ifp->if_snd);
605
606
	/* attach the interface */
607
	if_attach(ifp);
608
	bpfattach(ifp, DLT_RAW, 0);
609
610
	sc->sc_attached = 1;
611
612
	CURVNET_RESTORE();
613
614
	umb_init(sc);
615
	mtx_lock(&sc->sc_mutex);
616
}
617
618
static int
619
umb_detach(device_t dev)
620
{
621
	struct umb_softc *sc = device_get_softc(dev);
622
	struct ifnet *ifp = GET_IFP(sc);
623
624
	usb_proc_drain(&sc->sc_taskqueue);
625
626
	mtx_lock(&sc->sc_mutex);
627
	if (ifp != NULL && (ifp->if_drv_flags & IFF_DRV_RUNNING))
628
		umb_down(sc, 1);
629
	umb_close(sc);
630
	mtx_unlock(&sc->sc_mutex);
631
632
	usbd_transfer_unsetup(sc->sc_xfer, UMB_N_TRANSFER);
633
634
	free(sc->sc_tx_buf, M_DEVBUF);
635
	free(sc->sc_rx_buf, M_DEVBUF);
636
637
	usb_callout_drain(&sc->sc_statechg_timer);
638
639
	usb_proc_free(&sc->sc_taskqueue);
640
641
	mtx_destroy(&sc->sc_mutex);
642
643
	free(sc->sc_ctrl_msg, M_DEVBUF);
644
	free(sc->sc_resp_buf, M_DEVBUF);
645
646
	if (ifp != NULL && ifp->if_softc) {
647
		ifmedia_removeall(&sc->sc_im);
648
	}
649
	if (sc->sc_attached) {
650
		bpfdetach(ifp);
651
		if_detach(ifp);
652
		if_free(ifp);
653
		sc->sc_if = NULL;
654
	}
655
656
	return 0;
657
}
658
659
static void
660
umb_ncm_setup(struct umb_softc *sc, struct usb_config * config)
661
{
662
	usb_device_request_t req;
663
	struct ncm_ntb_parameters np;
664
	usb_error_t error;
665
666
	/* Query NTB tranfers sizes */
667
	req.bmRequestType = UT_READ_CLASS_INTERFACE;
668
	req.bRequest = NCM_GET_NTB_PARAMETERS;
669
	USETW(req.wValue, 0);
670
	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
671
	USETW(req.wLength, sizeof (np));
672
	mtx_lock(&sc->sc_mutex);
673
	error = usbd_do_request(sc->sc_udev, &sc->sc_mutex, &req, &np);
674
	mtx_unlock(&sc->sc_mutex);
675
	if (error == USB_ERR_NORMAL_COMPLETION &&
676
	    UGETW(np.wLength) == sizeof (np)) {
677
		config[UMB_BULK_RX].bufsize = UGETDW(np.dwNtbInMaxSize);
678
		config[UMB_BULK_TX].bufsize = UGETDW(np.dwNtbOutMaxSize);
679
	}
680
	sc->sc_rx_bufsz = config[UMB_BULK_RX].bufsize;
681
	sc->sc_tx_bufsz = config[UMB_BULK_TX].bufsize;
682
}
683
684
static int
685
umb_handle_request(device_t dev,
686
    const void *preq, void **pptr, uint16_t *plen,
687
    uint16_t offset, uint8_t *pstate)
688
{
689
	/* FIXME really implement */
690
691
	return (ENXIO);
692
}
693
694
static int
695
umb_suspend(device_t dev)
696
{
697
	device_printf(dev, "Suspending\n");
698
	return (0);
699
}
700
701
static int
702
umb_resume(device_t dev)
703
{
704
	device_printf(dev, "Resuming\n");
705
	return (0);
706
}
707
708
static int
709
umb_deactivate(device_t dev)
710
{
711
	struct umb_softc *sc = device_get_softc(dev);
712
	struct ifnet *ifp = GET_IFP(sc);
713
714
	if (ifp != NULL) {
715
		if_dead(ifp);
716
	}
717
	sc->sc_dying = 1;
718
	return 0;
719
}
720
721
static void
722
umb_close_bulkpipes(struct umb_softc *sc)
723
{
724
	struct ifnet *ifp = GET_IFP(sc);
725
726
	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
727
728
	umb_rxflush(sc);
729
	umb_txflush(sc);
730
731
	usbd_transfer_stop(sc->sc_xfer[UMB_BULK_RX]);
732
	usbd_transfer_stop(sc->sc_xfer[UMB_BULK_TX]);
733
}
734
735
static int
736
umb_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
737
{
738
	struct umb_softc *sc = ifp->if_softc;
739
	struct in_ifaddr *ia = (struct in_ifaddr *)data;
740
	struct ifreq *ifr = (struct ifreq *)data;
741
	int error = 0;
742
	struct umb_parameter mp;
743
744
	if (sc->sc_dying)
745
		return EIO;
746
747
	switch (cmd) {
748
	case SIOCSIFADDR:
749
		switch (ia->ia_ifa.ifa_addr->sa_family) {
750
		case AF_INET:
751
			break;
752
#ifdef INET6
753
		case AF_INET6:
754
			break;
755
#endif /* INET6 */
756
		default:
757
			error = EAFNOSUPPORT;
758
			break;
759
		}
760
		break;
761
	case SIOCSIFFLAGS:
762
		mtx_lock(&sc->sc_mutex);
763
		umb_add_task(sc, umb_state_task,
764
				&sc->sc_proc_state_task[0].hdr,
765
				&sc->sc_proc_state_task[1].hdr, 1);
766
		mtx_unlock(&sc->sc_mutex);
767
		break;
768
	case SIOCGUMBINFO:
769
		error = copyout(&sc->sc_info, ifr->ifr_ifru.ifru_data,
770
		    sizeof (sc->sc_info));
771
		break;
772
	case SIOCSUMBPARAM:
773
		error = priv_check(curthread, PRIV_NET_SETIFPHYS);
774
		if (error)
775
			break;
776
777
		if ((error = copyin(ifr->ifr_ifru.ifru_data, &mp, sizeof (mp))) != 0)
778
			break;
779
780
		if ((error = umb_setpin(sc, mp.op, mp.is_puk, mp.pin, mp.pinlen,
781
		    mp.newpin, mp.newpinlen)) != 0)
782
			break;
783
784
		if (mp.apnlen < 0 || mp.apnlen > sizeof (sc->sc_info.apn)) {
785
			error = EINVAL;
786
			break;
787
		}
788
		sc->sc_roaming = mp.roaming ? 1 : 0;
789
		memset(sc->sc_info.apn, 0, sizeof (sc->sc_info.apn));
790
		memcpy(sc->sc_info.apn, mp.apn, mp.apnlen);
791
		sc->sc_info.apnlen = mp.apnlen;
792
		memset(sc->sc_info.username, 0, sizeof (sc->sc_info.username));
793
		memcpy(sc->sc_info.username, mp.username, mp.usernamelen);
794
		sc->sc_info.usernamelen = mp.usernamelen;
795
		memset(sc->sc_info.password, 0, sizeof (sc->sc_info.password));
796
		memcpy(sc->sc_info.password, mp.password, mp.passwordlen);
797
		sc->sc_info.passwordlen = mp.passwordlen;
798
		sc->sc_info.preferredclasses = mp.preferredclasses;
799
		umb_setdataclass(sc);
800
		break;
801
	case SIOCGUMBPARAM:
802
		memset(&mp, 0, sizeof (mp));
803
		memcpy(mp.apn, sc->sc_info.apn, sc->sc_info.apnlen);
804
		mp.apnlen = sc->sc_info.apnlen;
805
		mp.roaming = sc->sc_roaming;
806
		mp.preferredclasses = sc->sc_info.preferredclasses;
807
		error = copyout(&mp, ifr->ifr_ifru.ifru_data, sizeof (mp));
808
		break;
809
	case SIOCSIFMTU:
810
		/* Does this include the NCM headers and tail? */
811
		if (ifr->ifr_mtu > ifp->if_mtu) {
812
			error = EINVAL;
813
			break;
814
		}
815
		ifp->if_mtu = ifr->ifr_mtu;
816
		break;
817
	case SIOCAIFADDR:
818
	case SIOCSIFDSTADDR:
819
	case SIOCADDMULTI:
820
	case SIOCDELMULTI:
821
		break;
822
	case SIOCGIFMEDIA:
823
		error = ifmedia_ioctl(ifp, ifr, &sc->sc_im, cmd);
824
		break;
825
	default:
826
		error = EINVAL;
827
		break;
828
	}
829
	return (error);
830
}
831
832
static void
833
umb_init(void *arg)
834
{
835
	struct umb_softc *sc = arg;
836
837
	mtx_lock(&sc->sc_mutex);
838
	umb_add_task(sc, umb_start_task,
839
			&sc->sc_proc_start_task[0].hdr,
840
			&sc->sc_proc_start_task[1].hdr, 0);
841
	mtx_unlock(&sc->sc_mutex);
842
}
843
844
static void
845
umb_input(struct ifnet *ifp, struct mbuf *m)
846
{
847
	struct mbuf *mn;
848
849
	while (m) {
850
		mn = m->m_nextpkt;
851
		m->m_nextpkt = NULL;
852
853
		BPF_MTAP(ifp, m);
854
855
		netisr_dispatch(NETISR_IP, m);
856
		m = mn;
857
	}
858
}
859
860
static int
861
umb_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
862
    struct route *rtp)
863
{
864
	int error;
865
866
	DPRINTFN(10, "%s: enter\n", __func__);
867
868
	switch (dst->sa_family) {
869
#ifdef INET6
870
	case AF_INET6:
871
		/* fall through */
872
#endif
873
	case AF_INET:
874
		break;
875
876
		/* silently drop dhclient packets */
877
	case AF_UNSPEC:
878
		m_freem(m);
879
		return (0);
880
881
		/* drop other packet types */
882
	default:
883
		m_freem(m);
884
		return (EAFNOSUPPORT);
885
	}
886
887
	/*
888
	 * Queue message on interface, and start output if interface
889
	 * not yet active.
890
	 */
891
	error = (ifp->if_transmit)(ifp, m);
892
	if (error) {
893
		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
894
		return (ENOBUFS);
895
	}
896
897
	return (0);
898
}
899
900
static void
901
umb_start(struct ifnet *ifp)
902
{
903
	struct umb_softc *sc = ifp->if_softc;
904
905
	if (sc->sc_dying || !(ifp->if_drv_flags & IFF_DRV_RUNNING))
906
		return;
907
908
	mtx_lock(&sc->sc_mutex);
909
	usbd_transfer_start(sc->sc_xfer[UMB_BULK_TX]);
910
	mtx_unlock(&sc->sc_mutex);
911
}
912
913
static void
914
umb_start_task(struct usb_proc_msg *msg)
915
{
916
	struct umb_task *task = (struct umb_task *)msg;
917
	struct umb_softc *sc = task->sc;
918
	struct ifnet *ifp = GET_IFP(sc);
919
920
	DPRINTF("%s()\n", __func__);
921
922
	mtx_assert(&sc->sc_mutex, MA_OWNED);
923
924
	ifp->if_drv_flags |= IFF_DRV_RUNNING;
925
926
	/* start interrupt transfer */
927
	usbd_transfer_start(sc->sc_xfer[UMB_INTR_RX]);
928
929
	umb_open(sc);
930
}
931
932
#if 0
933
static void
934
umb_watchdog(struct ifnet *ifp)
935
{
936
	struct umb_softc *sc = ifp->if_softc;
937
938
	if (sc->sc_dying)
939
		return;
940
941
	if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
942
	device_printf(sc->sc_dev, "watchdog timeout\n");
943
	usbd_transfer_drain(sc->sc_xfer[UMB_BULK_TX]);
944
	return;
945
}
946
#endif
947
948
static void
949
umb_statechg_timeout(void *arg)
950
{
951
	struct umb_softc *sc = arg;
952
	struct ifnet *ifp = GET_IFP(sc);
953
954
	mtx_assert(&sc->sc_mutex, MA_OWNED);
955
956
	if (sc->sc_info.regstate != MBIM_REGSTATE_ROAMING || sc->sc_roaming)
957
		if (ifp->if_flags & IFF_DEBUG)
958
			log(LOG_DEBUG, "%s: state change timeout\n",
959
					DEVNAM(sc));
960
961
	umb_add_task(sc, umb_state_task,
962
			&sc->sc_proc_state_task[0].hdr,
963
			&sc->sc_proc_state_task[1].hdr, 0);
964
}
965
966
static int
967
umb_mediachange(struct ifnet * ifp)
968
{
969
	return 0;
970
}
971
972
static void
973
umb_mediastatus(struct ifnet * ifp, struct ifmediareq * imr)
974
{
975
	switch (ifp->if_link_state) {
976
	case LINK_STATE_UP:
977
		imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
978
		break;
979
	case LINK_STATE_DOWN:
980
		imr->ifm_status = IFM_AVALID;
981
		break;
982
	default:
983
		imr->ifm_status = 0;
984
		break;
985
	}
986
}
987
988
static void
989
umb_add_task(struct umb_softc *sc, usb_proc_callback_t callback,
990
		struct usb_proc_msg *t0, struct usb_proc_msg *t1, int sync)
991
{
992
	struct umb_task * task;
993
994
	mtx_assert(&sc->sc_mutex, MA_OWNED);
995
996
	if (usb_proc_is_gone(&sc->sc_taskqueue)) {
997
		return;
998
	}
999
1000
	task = usb_proc_msignal(&sc->sc_taskqueue, t0, t1);
1001
1002
	task->hdr.pm_callback = callback;
1003
	task->sc = sc;
1004
1005
	if (sync) {
1006
		usb_proc_mwait(&sc->sc_taskqueue, t0, t1);
1007
	}
1008
}
1009
1010
static void
1011
umb_newstate(struct umb_softc *sc, enum umb_state newstate, int flags)
1012
{
1013
	struct ifnet *ifp = GET_IFP(sc);
1014
1015
	if (newstate == sc->sc_state)
1016
		return;
1017
	if (((flags & UMB_NS_DONT_DROP) && newstate < sc->sc_state) ||
1018
	    ((flags & UMB_NS_DONT_RAISE) && newstate > sc->sc_state))
1019
		return;
1020
	if (ifp->if_flags & IFF_DEBUG)
1021
		log(LOG_DEBUG, "%s: state going %s from '%s' to '%s'\n",
1022
		    DEVNAM(sc), newstate > sc->sc_state ? "up" : "down",
1023
		    umb_istate(sc->sc_state), umb_istate(newstate));
1024
	sc->sc_state = newstate;
1025
	umb_add_task(sc, umb_state_task,
1026
			&sc->sc_proc_state_task[0].hdr,
1027
			&sc->sc_proc_state_task[1].hdr, 0);
1028
}
1029
1030
static void
1031
umb_state_task(struct usb_proc_msg *msg)
1032
{
1033
	struct umb_task *task = (struct umb_task *)msg;
1034
	struct umb_softc *sc = task->sc;
1035
	struct ifnet *ifp = GET_IFP(sc);
1036
	struct ifreq ifr;
1037
	int	 state;
1038
1039
	DPRINTF("%s()\n", __func__);
1040
1041
	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
1042
		/*
1043
		 * Query the registration state until we're with the home
1044
		 * network again.
1045
		 */
1046
		umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY, NULL, 0);
1047
		return;
1048
	}
1049
1050
	if (ifp->if_flags & IFF_UP)
1051
		umb_up(sc);
1052
	else
1053
		umb_down(sc, 0);
1054
1055
	state = (sc->sc_state == UMB_S_UP) ? LINK_STATE_UP : LINK_STATE_DOWN;
1056
	if (ifp->if_link_state != state) {
1057
		if (ifp->if_flags & IFF_DEBUG)
1058
			log(LOG_DEBUG, "%s: link state changed from %s to %s\n",
1059
			    DEVNAM(sc),
1060
			    (ifp->if_link_state == LINK_STATE_UP)
1061
			    ? "up" : "down",
1062
			    (state == LINK_STATE_UP) ? "up" : "down");
1063
		ifp->if_link_state = state;
1064
		if (state != LINK_STATE_UP) {
1065
			/*
1066
			 * Purge any existing addresses
1067
			 */
1068
			memset(sc->sc_info.ipv4dns, 0,
1069
			    sizeof (sc->sc_info.ipv4dns));
1070
			mtx_unlock(&sc->sc_mutex);
1071
			CURVNET_SET_QUIET(vnet0);
1072
			if (in_control(NULL, SIOCGIFADDR, (caddr_t)&ifr, ifp,
1073
				       curthread) == 0 &&
1074
			    satosin(&ifr.ifr_addr)->sin_addr.s_addr !=
1075
			    INADDR_ANY) {
1076
				in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr,
1077
					   ifp, curthread);
1078
			}
1079
			CURVNET_RESTORE();
1080
			mtx_lock(&sc->sc_mutex);
1081
		}
1082
		if_link_state_change(ifp, state);
1083
	}
1084
}
1085
1086
static void
1087
umb_up(struct umb_softc *sc)
1088
{
1089
	struct ifnet *ifp = GET_IFP(sc);
1090
1091
	switch (sc->sc_state) {
1092
	case UMB_S_DOWN:
1093
		DPRINTF("init: opening ...\n");
1094
		umb_open(sc);
1095
		break;
1096
	case UMB_S_OPEN:
1097
		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED) {
1098
			if (sc->sc_cid == -1) {
1099
				DPRINTF("init: allocating CID ...\n");
1100
				umb_allocate_cid(sc);
1101
				break;
1102
			} else
1103
				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
1104
		} else {
1105
			DPRINTF("init: turning radio on ...\n");
1106
			umb_radio(sc, 1);
1107
			break;
1108
		}
1109
		/*FALLTHROUGH*/
1110
	case UMB_S_CID:
1111
		DPRINTF("init: sending FCC auth ...\n");
1112
		umb_send_fcc_auth(sc);
1113
		break;
1114
	case UMB_S_RADIO:
1115
		DPRINTF("init: checking SIM state ...\n");
1116
		umb_cmd(sc, MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CMDOP_QRY,
1117
		    NULL, 0);
1118
		break;
1119
	case UMB_S_SIMREADY:
1120
		DPRINTF("init: attaching ...\n");
1121
		umb_packet_service(sc, 1);
1122
		break;
1123
	case UMB_S_ATTACHED:
1124
		sc->sc_tx_seq = 0;
1125
		DPRINTF("init: connecting ...\n");
1126
		umb_connect(sc);
1127
		break;
1128
	case UMB_S_CONNECTED:
1129
		DPRINTF("init: getting IP config ...\n");
1130
		umb_qry_ipconfig(sc);
1131
		break;
1132
	case UMB_S_UP:
1133
		DPRINTF("init: reached state UP\n");
1134
		if (!(ifp->if_flags & IFF_DRV_RUNNING)) {
1135
			ifp->if_drv_flags |= IFF_DRV_RUNNING;
1136
			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1137
			umb_rx(sc);
1138
		}
1139
		break;
1140
	}
1141
	if (sc->sc_state < UMB_S_UP)
1142
		usb_callout_reset(&sc->sc_statechg_timer,
1143
		    UMB_STATE_CHANGE_TIMEOUT * hz, umb_statechg_timeout, sc);
1144
	else {
1145
		usb_callout_stop(&sc->sc_statechg_timer);
1146
	}
1147
	return;
1148
}
1149
1150
static void
1151
umb_down(struct umb_softc *sc, int force)
1152
{
1153
	umb_close_bulkpipes(sc);
1154
1155
	switch (sc->sc_state) {
1156
	case UMB_S_UP:
1157
	case UMB_S_CONNECTED:
1158
		DPRINTF("stop: disconnecting ...\n");
1159
		umb_disconnect(sc);
1160
		if (!force)
1161
			break;
1162
		/*FALLTHROUGH*/
1163
	case UMB_S_ATTACHED:
1164
		DPRINTF("stop: detaching ...\n");
1165
		umb_packet_service(sc, 0);
1166
		if (!force)
1167
			break;
1168
		/*FALLTHROUGH*/
1169
	case UMB_S_SIMREADY:
1170
	case UMB_S_RADIO:
1171
		DPRINTF("stop: turning radio off ...\n");
1172
		umb_radio(sc, 0);
1173
		if (!force)
1174
			break;
1175
		/*FALLTHROUGH*/
1176
	case UMB_S_CID:
1177
	case UMB_S_OPEN:
1178
	case UMB_S_DOWN:
1179
		/* Do not close the device */
1180
		DPRINTF("stop: reached state DOWN\n");
1181
		break;
1182
	}
1183
	if (force)
1184
		sc->sc_state = UMB_S_OPEN;
1185
1186
	if (sc->sc_state > UMB_S_OPEN)
1187
		usb_callout_reset(&sc->sc_statechg_timer,
1188
		    UMB_STATE_CHANGE_TIMEOUT * hz, umb_statechg_timeout, sc);
1189
	else
1190
		usb_callout_stop(&sc->sc_statechg_timer);
1191
}
1192
1193
static void
1194
umb_get_response_task(struct usb_proc_msg *msg)
1195
{
1196
	struct umb_task *task = (struct umb_task *)msg;
1197
	struct umb_softc *sc = task->sc;
1198
	int	 len;
1199
1200
	DPRINTF("%s()\n", __func__);
1201
	/*
1202
	 * Function is required to send on RESPONSE_AVAILABLE notification for
1203
	 * each encapsulated response that is to be processed by the host.
1204
	 * But of course, we can receive multiple notifications before the
1205
	 * response task is run.
1206
	 */
1207
	while (sc->sc_nresp > 0) {
1208
		--sc->sc_nresp;
1209
		len = sc->sc_ctrl_len;
1210
		if (umb_get_encap_response(sc, sc->sc_resp_buf, &len))
1211
			umb_decode_response(sc, sc->sc_resp_buf, len);
1212
	}
1213
}
1214
1215
static void
1216
umb_decode_response(struct umb_softc *sc, void *response, int len)
1217
{
1218
	struct mbim_msghdr *hdr = response;
1219
	struct mbim_fragmented_msg_hdr *fraghdr;
1220
	uint32_t type;
1221
1222
	DPRINTFN(3, "got response: len %d\n", len);
1223
	DDUMPN(4, response, len);
1224
1225
	if (len < sizeof (*hdr) || le32toh(hdr->len) != len) {
1226
		/*
1227
		 * We should probably cancel a transaction, but since the
1228
		 * message is too short, we cannot decode the transaction
1229
		 * id (tid) and hence don't know, whom to cancel. Must wait
1230
		 * for the timeout.
1231
		 */
1232
		DPRINTF("received short response (len %d)\n",
1233
		    len);
1234
		return;
1235
	}
1236
1237
	/*
1238
	 * XXX FIXME: if message is fragmented, store it until last frag
1239
	 *	is received and then re-assemble all fragments.
1240
	 */
1241
	type = le32toh(hdr->type);
1242
	switch (type) {
1243
	case MBIM_INDICATE_STATUS_MSG:
1244
	case MBIM_COMMAND_DONE:
1245
		fraghdr = response;
1246
		if (le32toh(fraghdr->frag.nfrag) != 1) {
1247
			DPRINTF("discarding fragmented messages\n");
1248
			return;
1249
		}
1250
		break;
1251
	default:
1252
		break;
1253
	}
1254
1255
	DPRINTF("<- rcv %s (tid %u)\n", umb_request2str(type),
1256
	    le32toh(hdr->tid));
1257
	switch (type) {
1258
	case MBIM_FUNCTION_ERROR_MSG:
1259
	case MBIM_HOST_ERROR_MSG:
1260
	{
1261
		struct mbim_f2h_hosterr *e;
1262
		int	 err;
1263
1264
		if (len >= sizeof (*e)) {
1265
			e = response;
1266
			err = le32toh(e->err);
1267
1268
			DPRINTF("%s message, error %s (tid %u)\n",
1269
			    umb_request2str(type),
1270
			    umb_error2str(err), le32toh(hdr->tid));
1271
			if (err == MBIM_ERROR_NOT_OPENED)
1272
				umb_newstate(sc, UMB_S_DOWN, 0);
1273
		}
1274
		break;
1275
	}
1276
	case MBIM_INDICATE_STATUS_MSG:
1277
		umb_handle_indicate_status_msg(sc, response, len);
1278
		break;
1279
	case MBIM_OPEN_DONE:
1280
		umb_handle_opendone_msg(sc, response, len);
1281
		break;
1282
	case MBIM_CLOSE_DONE:
1283
		umb_handle_closedone_msg(sc, response, len);
1284
		break;
1285
	case MBIM_COMMAND_DONE:
1286
		umb_command_done(sc, response, len);
1287
		break;
1288
	default:
1289
		DPRINTF("discard message %s\n",
1290
		    umb_request2str(type));
1291
		break;
1292
	}
1293
}
1294
1295
static void
1296
umb_handle_indicate_status_msg(struct umb_softc *sc, void *data, int len)
1297
{
1298
	struct mbim_f2h_indicate_status *m = data;
1299
	uint32_t infolen;
1300
	uint32_t cid;
1301
1302
	if (len < sizeof (*m)) {
1303
		DPRINTF("discard short %s message\n",
1304
		    umb_request2str(le32toh(m->hdr.type)));
1305
		return;
1306
	}
1307
	if (memcmp(m->devid, umb_uuid_basic_connect, sizeof (m->devid))) {
1308
		DPRINTF("discard %s message for other UUID '%s'\n",
1309
		    umb_request2str(le32toh(m->hdr.type)),
1310
		    umb_uuid2str(m->devid));
1311
		return;
1312
	}
1313
	infolen = le32toh(m->infolen);
1314
	if (len < sizeof (*m) + infolen) {
1315
		DPRINTF("discard truncated %s message (want %d, got %d)\n",
1316
		    umb_request2str(le32toh(m->hdr.type)),
1317
		    (int)sizeof (*m) + infolen, len);
1318
		return;
1319
	}
1320
1321
	cid = le32toh(m->cid);
1322
	DPRINTF("indicate %s status\n", umb_cid2str(cid));
1323
	umb_decode_cid(sc, cid, m->info, infolen);
1324
}
1325
1326
static void
1327
umb_handle_opendone_msg(struct umb_softc *sc, void *data, int len)
1328
{
1329
	struct mbim_f2h_openclosedone *resp = data;
1330
	struct ifnet *ifp = GET_IFP(sc);
1331
	uint32_t status;
1332
1333
	status = le32toh(resp->status);
1334
	if (status == MBIM_STATUS_SUCCESS) {
1335
		if (sc->sc_maxsessions == 0) {
1336
			umb_cmd(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_QRY, NULL,
1337
			    0);
1338
			umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_QRY, NULL, 0);
1339
			umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_QRY,
1340
			    NULL, 0);
1341
		}
1342
		umb_newstate(sc, UMB_S_OPEN, UMB_NS_DONT_DROP);
1343
	} else if (ifp->if_flags & IFF_DEBUG)
1344
		log(LOG_ERR, "%s: open error: %s\n", DEVNAM(sc),
1345
		    umb_status2str(status));
1346
	return;
1347
}
1348
1349
static void
1350
umb_handle_closedone_msg(struct umb_softc *sc, void *data, int len)
1351
{
1352
	struct mbim_f2h_openclosedone *resp = data;
1353
	uint32_t status;
1354
1355
	status = le32toh(resp->status);
1356
	if (status == MBIM_STATUS_SUCCESS)
1357
		umb_newstate(sc, UMB_S_DOWN, 0);
1358
	else
1359
		DPRINTF("close error: %s\n",
1360
		    umb_status2str(status));
1361
	return;
1362
}
1363
1364
static inline void
1365
umb_getinfobuf(char *in, int inlen, uint32_t offs, uint32_t sz,
1366
    void *out, size_t outlen)
1367
{
1368
	offs = le32toh(offs);
1369
	sz = le32toh(sz);
1370
	if (inlen >= offs + sz) {
1371
		memset(out, 0, outlen);
1372
		memcpy(out, in + offs, MIN(sz, outlen));
1373
	}
1374
}
1375
1376
static inline int
1377
umb_padding(void *data, int len, size_t sz)
1378
{
1379
	char *p = data;
1380
	int np = 0;
1381
1382
	while (len < sz && (len % 4) != 0) {
1383
		*p++ = '\0';
1384
		len++;
1385
		np++;
1386
	}
1387
	return np;
1388
}
1389
1390
static inline int
1391
umb_addstr(void *buf, size_t bufsz, int *offs, void *str, int slen,
1392
    uint32_t *offsmember, uint32_t *sizemember)
1393
{
1394
	if (*offs + slen > bufsz)
1395
		return 0;
1396
1397
	*sizemember = htole32((uint32_t)slen);
1398
	if (slen && str) {
1399
		*offsmember = htole32((uint32_t)*offs);
1400
		memcpy((char *)buf + *offs, str, slen);
1401
		*offs += slen;
1402
		*offs += umb_padding(buf, *offs, bufsz);
1403
	} else
1404
		*offsmember = htole32(0);
1405
	return 1;
1406
}
1407
1408
static void
1409
umb_in_len2mask(struct in_addr *mask, int len)
1410
{
1411
	int i;
1412
	u_char *p;
1413
1414
	p = (u_char *)mask;
1415
	memset(mask, 0, sizeof (*mask));
1416
	for (i = 0; i < len / 8; i++)
1417
		p[i] = 0xff;
1418
	if (len % 8)
1419
		p[i] = (0xff00 >> (len % 8)) & 0xff;
1420
}
1421
1422
static int
1423
umb_decode_register_state(struct umb_softc *sc, void *data, int len)
1424
{
1425
	struct mbim_cid_registration_state_info *rs = data;
1426
	struct ifnet *ifp = GET_IFP(sc);
1427
1428
	if (len < sizeof (*rs))
1429
		return 0;
1430
	sc->sc_info.nwerror = le32toh(rs->nwerror);
1431
	sc->sc_info.regstate = le32toh(rs->regstate);
1432
	sc->sc_info.regmode = le32toh(rs->regmode);
1433
	sc->sc_info.cellclass = le32toh(rs->curcellclass);
1434
1435
	/* XXX should we remember the provider_id? */
1436
	umb_getinfobuf(data, len, rs->provname_offs, rs->provname_size,
1437
	    sc->sc_info.provider, sizeof (sc->sc_info.provider));
1438
	umb_getinfobuf(data, len, rs->roamingtxt_offs, rs->roamingtxt_size,
1439
	    sc->sc_info.roamingtxt, sizeof (sc->sc_info.roamingtxt));
1440
1441
	DPRINTFN(2, "%s, availclass 0x%x, class 0x%x, regmode %d\n",
1442
	    umb_regstate(sc->sc_info.regstate),
1443
	    le32toh(rs->availclasses), sc->sc_info.cellclass,
1444
	    sc->sc_info.regmode);
1445
1446
	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING &&
1447
	    !sc->sc_roaming &&
1448
	    sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED) {
1449
		if (ifp->if_flags & IFF_DEBUG)
1450
			log(LOG_INFO,
1451
			    "%s: disconnecting from roaming network\n",
1452
			    DEVNAM(sc));
1453
		umb_disconnect(sc);
1454
	}
1455
	return 1;
1456
}
1457
1458
static int
1459
umb_decode_devices_caps(struct umb_softc *sc, void *data, int len)
1460
{
1461
	struct mbim_cid_device_caps *dc = data;
1462
1463
	if (len < sizeof (*dc))
1464
		return 0;
1465
	sc->sc_maxsessions = le32toh(dc->max_sessions);
1466
	sc->sc_info.supportedclasses = le32toh(dc->dataclass);
1467
	umb_getinfobuf(data, len, dc->devid_offs, dc->devid_size,
1468
	    sc->sc_info.devid, sizeof (sc->sc_info.devid));
1469
	umb_getinfobuf(data, len, dc->fwinfo_offs, dc->fwinfo_size,
1470
	    sc->sc_info.fwinfo, sizeof (sc->sc_info.fwinfo));
1471
	umb_getinfobuf(data, len, dc->hwinfo_offs, dc->hwinfo_size,
1472
	    sc->sc_info.hwinfo, sizeof (sc->sc_info.hwinfo));
1473
	DPRINTFN(2, "max sessions %d, supported classes 0x%x\n",
1474
	    sc->sc_maxsessions, sc->sc_info.supportedclasses);
1475
	return 1;
1476
}
1477
1478
static int
1479
umb_decode_subscriber_status(struct umb_softc *sc, void *data, int len)
1480
{
1481
	struct mbim_cid_subscriber_ready_info *si = data;
1482
	struct ifnet *ifp = GET_IFP(sc);
1483
	int	npn;
1484
1485
	if (len < sizeof (*si))
1486
		return 0;
1487
	sc->sc_info.sim_state = le32toh(si->ready);
1488
1489
	umb_getinfobuf(data, len, si->sid_offs, si->sid_size,
1490
	    sc->sc_info.sid, sizeof (sc->sc_info.sid));
1491
	umb_getinfobuf(data, len, si->icc_offs, si->icc_size,
1492
	    sc->sc_info.iccid, sizeof (sc->sc_info.iccid));
1493
1494
	npn = le32toh(si->no_pn);
1495
	if (npn > 0)
1496
		umb_getinfobuf(data, len, si->pn[0].offs, si->pn[0].size,
1497
		    sc->sc_info.pn, sizeof (sc->sc_info.pn));
1498
	else
1499
		memset(sc->sc_info.pn, 0, sizeof (sc->sc_info.pn));
1500
1501
	if (sc->sc_info.sim_state == MBIM_SIMSTATE_LOCKED)
1502
		sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1503
	if (ifp->if_flags & IFF_DEBUG)
1504
		log(LOG_INFO, "%s: SIM %s\n", DEVNAM(sc),
1505
		    umb_simstate(sc->sc_info.sim_state));
1506
	if (sc->sc_info.sim_state == MBIM_SIMSTATE_INITIALIZED)
1507
		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_DROP);
1508
	return 1;
1509
}
1510
1511
static int
1512
umb_decode_radio_state(struct umb_softc *sc, void *data, int len)
1513
{
1514
	struct mbim_cid_radio_state_info *rs = data;
1515
	struct ifnet *ifp = GET_IFP(sc);
1516
1517
	if (len < sizeof (*rs))
1518
		return 0;
1519
1520
	sc->sc_info.hw_radio_on =
1521
	    (le32toh(rs->hw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1522
	sc->sc_info.sw_radio_on =
1523
	    (le32toh(rs->sw_state) == MBIM_RADIO_STATE_ON) ? 1 : 0;
1524
	if (!sc->sc_info.hw_radio_on) {
1525
		device_printf(sc->sc_dev, "radio is disabled by hardware switch\n");
1526
		/*
1527
		 * XXX do we need a time to poll the state of the rfkill switch
1528
		 *	or will the device send an unsolicited notification
1529
		 *	in case the state changes?
1530
		 */
1531
		umb_newstate(sc, UMB_S_OPEN, 0);
1532
	} else if (!sc->sc_info.sw_radio_on) {
1533
		if (ifp->if_flags & IFF_DEBUG)
1534
			log(LOG_INFO, "%s: radio is off\n", DEVNAM(sc));
1535
		umb_newstate(sc, UMB_S_OPEN, 0);
1536
	} else
1537
		umb_newstate(sc, UMB_S_RADIO, UMB_NS_DONT_DROP);
1538
	return 1;
1539
}
1540
1541
static int
1542
umb_decode_pin(struct umb_softc *sc, void *data, int len)
1543
{
1544
	struct mbim_cid_pin_info *pi = data;
1545
	struct ifnet *ifp = GET_IFP(sc);
1546
	uint32_t	attempts_left;
1547
1548
	if (len < sizeof (*pi))
1549
		return 0;
1550
1551
	attempts_left = le32toh(pi->remaining_attempts);
1552
	if (attempts_left != 0xffffffff)
1553
		sc->sc_info.pin_attempts_left = attempts_left;
1554
1555
	switch (le32toh(pi->state)) {
1556
	case MBIM_PIN_STATE_UNLOCKED:
1557
		sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1558
		break;
1559
	case MBIM_PIN_STATE_LOCKED:
1560
		switch (le32toh(pi->type)) {
1561
		case MBIM_PIN_TYPE_PIN1:
1562
			sc->sc_info.pin_state = UMB_PIN_REQUIRED;
1563
			break;
1564
		case MBIM_PIN_TYPE_PUK1:
1565
			sc->sc_info.pin_state = UMB_PUK_REQUIRED;
1566
			break;
1567
		case MBIM_PIN_TYPE_PIN2:
1568
		case MBIM_PIN_TYPE_PUK2:
1569
			/* Assume that PIN1 was accepted */
1570
			sc->sc_info.pin_state = UMB_PIN_UNLOCKED;
1571
			break;
1572
		}
1573
		break;
1574
	}
1575
	if (ifp->if_flags & IFF_DEBUG)
1576
		log(LOG_INFO, "%s: %s state %s (%d attempts left)\n",
1577
		    DEVNAM(sc), umb_pin_type(le32toh(pi->type)),
1578
		    (le32toh(pi->state) == MBIM_PIN_STATE_UNLOCKED) ?
1579
			"unlocked" : "locked",
1580
		    le32toh(pi->remaining_attempts));
1581
1582
	/*
1583
	 * In case the PIN was set after IFF_UP, retrigger the state machine
1584
	 */
1585
	umb_add_task(sc, umb_state_task,
1586
			&sc->sc_proc_state_task[0].hdr,
1587
			&sc->sc_proc_state_task[1].hdr, 0);
1588
	return 1;
1589
}
1590
1591
static int
1592
umb_decode_packet_service(struct umb_softc *sc, void *data, int len)
1593
{
1594
	struct mbim_cid_packet_service_info *psi = data;
1595
	int	 state, highestclass;
1596
	uint64_t up_speed, down_speed;
1597
	struct ifnet *ifp = GET_IFP(sc);
1598
1599
	if (len < sizeof (*psi))
1600
		return 0;
1601
1602
	sc->sc_info.nwerror = le32toh(psi->nwerror);
1603
	state = le32toh(psi->state);
1604
	highestclass = le32toh(psi->highest_dataclass);
1605
	up_speed = le64toh(psi->uplink_speed);
1606
	down_speed = le64toh(psi->downlink_speed);
1607
	if (sc->sc_info.packetstate  != state ||
1608
	    sc->sc_info.uplink_speed != up_speed ||
1609
	    sc->sc_info.downlink_speed != down_speed) {
1610
		if (ifp->if_flags & IFF_DEBUG) {
1611
			log(LOG_INFO, "%s: packet service ", DEVNAM(sc));
1612
			if (sc->sc_info.packetstate  != state)
1613
				log(LOG_INFO, "changed from %s to ",
1614
				    umb_packet_state(sc->sc_info.packetstate));
1615
			log(LOG_INFO, "%s, class %s, speed: %" PRIu64 " up / %" PRIu64 " down\n",
1616
			    umb_packet_state(state),
1617
			    umb_dataclass(highestclass), up_speed, down_speed);
1618
		}
1619
	}
1620
	sc->sc_info.packetstate = state;
1621
	sc->sc_info.highestclass = highestclass;
1622
	sc->sc_info.uplink_speed = up_speed;
1623
	sc->sc_info.downlink_speed = down_speed;
1624
1625
	if (sc->sc_info.regmode == MBIM_REGMODE_AUTOMATIC) {
1626
		/*
1627
		 * For devices using automatic registration mode, just proceed,
1628
		 * once registration has completed.
1629
		 */
1630
		if (ifp->if_flags & IFF_UP) {
1631
			switch (sc->sc_info.regstate) {
1632
			case MBIM_REGSTATE_HOME:
1633
			case MBIM_REGSTATE_ROAMING:
1634
			case MBIM_REGSTATE_PARTNER:
1635
				umb_newstate(sc, UMB_S_ATTACHED,
1636
				    UMB_NS_DONT_DROP);
1637
				break;
1638
			default:
1639
				break;
1640
			}
1641
		} else
1642
			umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1643
	} else switch (sc->sc_info.packetstate) {
1644
	case MBIM_PKTSERVICE_STATE_ATTACHED:
1645
		umb_newstate(sc, UMB_S_ATTACHED, UMB_NS_DONT_DROP);
1646
		break;
1647
	case MBIM_PKTSERVICE_STATE_DETACHED:
1648
		umb_newstate(sc, UMB_S_SIMREADY, UMB_NS_DONT_RAISE);
1649
		break;
1650
	}
1651
	return 1;
1652
}
1653
1654
static int
1655
umb_decode_signal_state(struct umb_softc *sc, void *data, int len)
1656
{
1657
	struct mbim_cid_signal_state *ss = data;
1658
	struct ifnet *ifp = GET_IFP(sc);
1659
	int	 rssi;
1660
1661
	if (len < sizeof (*ss))
1662
		return 0;
1663
1664
	if (le32toh(ss->rssi) == 99)
1665
		rssi = UMB_VALUE_UNKNOWN;
1666
	else {
1667
		rssi = -113 + 2 * le32toh(ss->rssi);
1668
		if ((ifp->if_flags & IFF_DEBUG) && sc->sc_info.rssi != rssi &&
1669
		    sc->sc_state >= UMB_S_CONNECTED)
1670
			log(LOG_INFO, "%s: rssi %d dBm\n", DEVNAM(sc), rssi);
1671
	}
1672
	sc->sc_info.rssi = rssi;
1673
	sc->sc_info.ber = le32toh(ss->err_rate);
1674
	if (sc->sc_info.ber == -99)
1675
		sc->sc_info.ber = UMB_VALUE_UNKNOWN;
1676
	return 1;
1677
}
1678
1679
static int
1680
umb_decode_connect_info(struct umb_softc *sc, void *data, int len)
1681
{
1682
	struct mbim_cid_connect_info *ci = data;
1683
	struct ifnet *ifp = GET_IFP(sc);
1684
	int	 act;
1685
1686
	if (len < sizeof (*ci))
1687
		return 0;
1688
1689
	if (le32toh(ci->sessionid) != umb_session_id) {
1690
		DPRINTF("discard connection info for session %u\n",
1691
		    le32toh(ci->sessionid));
1692
		return 1;
1693
	}
1694
	if (memcmp(ci->context, umb_uuid_context_internet,
1695
	    sizeof (ci->context))) {
1696
		DPRINTF("discard connection info for other context\n");
1697
		return 1;
1698
	}
1699
	act = le32toh(ci->activation);
1700
	if (sc->sc_info.activation != act) {
1701
		if (ifp->if_flags & IFF_DEBUG)
1702
			log(LOG_INFO, "%s: connection %s\n", DEVNAM(sc),
1703
			    umb_activation(act));
1704
		if ((ifp->if_flags & IFF_DEBUG) &&
1705
		    le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_DEFAULT &&
1706
		    le32toh(ci->iptype) != MBIM_CONTEXT_IPTYPE_IPV4)
1707
			log(LOG_DEBUG, "%s: got iptype %d connection\n",
1708
			    DEVNAM(sc), le32toh(ci->iptype));
1709
1710
		sc->sc_info.activation = act;
1711
		sc->sc_info.nwerror = le32toh(ci->nwerror);
1712
1713
		if (sc->sc_info.activation == MBIM_ACTIVATION_STATE_ACTIVATED)
1714
			umb_newstate(sc, UMB_S_CONNECTED, UMB_NS_DONT_DROP);
1715
		else if (sc->sc_info.activation ==
1716
		    MBIM_ACTIVATION_STATE_DEACTIVATED)
1717
			umb_newstate(sc, UMB_S_ATTACHED, 0);
1718
		/* else: other states are purely transitional */
1719
	}
1720
	return 1;
1721
}
1722
1723
static int
1724
umb_add_inet_config(struct umb_softc *sc, struct in_addr ip, u_int prefixlen,
1725
    struct in_addr gw)
1726
{
1727
	struct ifnet *ifp = GET_IFP(sc);
1728
	struct in_aliasreq ifra;
1729
	struct sockaddr_in *sin;
1730
	int	 rv;
1731
1732
	memset(&ifra, 0, sizeof (ifra));
1733
	sin = (struct sockaddr_in *)&ifra.ifra_addr;
1734
	sin->sin_family = AF_INET;
1735
	sin->sin_len = sizeof (*sin);
1736
	sin->sin_addr = ip;
1737
1738
	sin = (struct sockaddr_in *)&ifra.ifra_dstaddr;
1739
	sin->sin_family = AF_INET;
1740
	sin->sin_len = sizeof (*sin);
1741
	sin->sin_addr = gw;
1742
1743
	sin = (struct sockaddr_in *)&ifra.ifra_mask;
1744
	sin->sin_family = AF_INET;
1745
	sin->sin_len = sizeof (*sin);
1746
	umb_in_len2mask(&sin->sin_addr, prefixlen);
1747
1748
	mtx_unlock(&sc->sc_mutex);
1749
	CURVNET_SET_QUIET(vnet0);
1750
	rv = in_control(NULL, SIOCAIFADDR, (caddr_t)&ifra, ifp, curthread);
1751
	CURVNET_RESTORE();
1752
	mtx_lock(&sc->sc_mutex);
1753
	if (rv != 0) {
1754
		device_printf(sc->sc_dev, "unable to set IPv4 address, error %d\n",
1755
		    rv);
1756
		return rv;
1757
	}
1758
1759
	if (ifp->if_flags & IFF_DEBUG)
1760
		log(LOG_INFO, "%s: IPv4 addr %s, mask %s, "
1761
		    "gateway %s\n", DEVNAM(sc),
1762
		    umb_ntop(sintosa(&ifra.ifra_addr)),
1763
		    umb_ntop(sintosa(&ifra.ifra_mask)),
1764
		    umb_ntop(sintosa(&ifra.ifra_dstaddr)));
1765
1766
	return 0;
1767
}
1768
1769
static int
1770
umb_decode_ip_configuration(struct umb_softc *sc, void *data, int len)
1771
{
1772
	struct mbim_cid_ip_configuration_info *ic = data;
1773
	struct ifnet *ifp = GET_IFP(sc);
1774
	uint32_t avail_v4;
1775
	uint32_t val;
1776
	int	 n, i;
1777
	int	 off;
1778
	struct mbim_cid_ipv4_element ipv4elem;
1779
	struct in_addr addr, gw;
1780
	int	 state = -1;
1781
	int	 rv;
1782
1783
	if (len < sizeof (*ic))
1784
		return 0;
1785
	if (le32toh(ic->sessionid) != umb_session_id) {
1786
		DPRINTF("ignore IP configuration for session id %d\n",
1787
		    le32toh(ic->sessionid));
1788
		return 0;
1789
	}
1790
1791
	/*
1792
	 * IPv4 configuration
1793
	 */
1794
	avail_v4 = le32toh(ic->ipv4_available);
1795
	if ((avail_v4 & (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) ==
1796
	    (MBIM_IPCONF_HAS_ADDRINFO | MBIM_IPCONF_HAS_GWINFO)) {
1797
		n = le32toh(ic->ipv4_naddr);
1798
		off = le32toh(ic->ipv4_addroffs);
1799
1800
		if (n == 0 || off + sizeof (ipv4elem) > len)
1801
			goto tryv6;
1802
		if (n != 1 && ifp->if_flags & IFF_DEBUG)
1803
			log(LOG_INFO, "%s: more than one IPv4 addr: %d\n",
1804
			    DEVNAM(sc), n);
1805
1806
		/* Only pick the first one */
1807
		memcpy(&ipv4elem, (char *)data + off, sizeof (ipv4elem));
1808
		ipv4elem.prefixlen = le32toh(ipv4elem.prefixlen);
1809
		addr.s_addr = ipv4elem.addr;
1810
1811
		off = le32toh(ic->ipv4_gwoffs);
1812
		if (off + sizeof (gw) > len)
1813
			goto done;
1814
		memcpy(&gw, (char *)data + off, sizeof (gw));
1815
1816
		rv = umb_add_inet_config(sc, addr, ipv4elem.prefixlen, gw);
1817
		if (rv == 0)
1818
			state = UMB_S_UP;
1819
	}
1820
1821
	memset(sc->sc_info.ipv4dns, 0, sizeof (sc->sc_info.ipv4dns));
1822
	if (avail_v4 & MBIM_IPCONF_HAS_DNSINFO) {
1823
		n = le32toh(ic->ipv4_ndnssrv);
1824
		off = le32toh(ic->ipv4_dnssrvoffs);
1825
		i = 0;
1826
		while (n-- > 0) {
1827
			if (off + sizeof (addr) > len)
1828
				break;
1829
			memcpy(&addr, (char *)data + off, sizeof(addr));
1830
			if (i < UMB_MAX_DNSSRV)
1831
				sc->sc_info.ipv4dns[i++] = addr;
1832
			off += sizeof(addr);
1833
		}
1834
	}
1835
1836
	if ((avail_v4 & MBIM_IPCONF_HAS_MTUINFO)) {
1837
		val = le32toh(ic->ipv4_mtu);
1838
		if (ifp->if_mtu != val && val <= sc->sc_maxpktlen) {
1839
			ifp->if_mtu = val;
1840
			if (ifp->if_mtu > val)
1841
				ifp->if_mtu = val;
1842
			if (ifp->if_flags & IFF_DEBUG)
1843
				log(LOG_INFO, "%s: MTU %d\n", DEVNAM(sc), val);
1844
		}
1845
	}
1846
1847
	avail_v4 = le32toh(ic->ipv6_available);
1848
	if ((ifp->if_flags & IFF_DEBUG) && avail_v4 & MBIM_IPCONF_HAS_ADDRINFO) {
1849
		/* XXX FIXME: IPv6 configuration missing */
1850
		log(LOG_INFO, "%s: ignoring IPv6 configuration\n", DEVNAM(sc));
1851
	}
1852
	if (state != -1)
1853
		umb_newstate(sc, state, 0);
1854
1855
tryv6:
1856
done:
1857
	return 1;
1858
}
1859
1860
static void
1861
umb_rx(struct umb_softc *sc)
1862
{
1863
	mtx_assert(&sc->sc_mutex, MA_OWNED);
1864
1865
	usbd_transfer_start(sc->sc_xfer[UMB_BULK_RX]);
1866
}
1867
1868
static void
1869
umb_rxeof(struct usb_xfer *xfer, usb_error_t status)
1870
{
1871
	struct umb_softc *sc = usbd_xfer_softc(xfer);
1872
	struct ifnet *ifp = GET_IFP(sc);
1873
	int actlen;
1874
	int aframes;
1875
	int i;
1876
1877
	DPRINTF("%s(%u): state=%u\n", __func__, status, USB_GET_STATE(xfer));
1878
1879
	mtx_assert(&sc->sc_mutex, MA_OWNED);
1880
1881
	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
1882
1883
	switch (USB_GET_STATE(xfer)) {
1884
	case USB_ST_TRANSFERRED:
1885
		DPRINTF("received %u bytes in %u frames\n", actlen, aframes);
1886
1887
		if (actlen == 0) {
1888
			if (sc->sc_rx_nerr >= 4)
1889
				/* throttle transfers */
1890
				usbd_xfer_set_interval(xfer, 500);
1891
			else
1892
				sc->sc_rx_nerr++;
1893
		}
1894
		else {
1895
			/* disable throttling */
1896
			usbd_xfer_set_interval(xfer, 0);
1897
			sc->sc_rx_nerr = 0;
1898
		}
1899
1900
		for(i = 0; i < aframes; i++) {
1901
			umb_decap(sc, xfer, i);
1902
		}
1903
1904
		/* fall through */
1905
	case USB_ST_SETUP:
1906
		usbd_xfer_set_frame_data(xfer, 0, sc->sc_rx_buf,
1907
				sc->sc_rx_bufsz);
1908
		usbd_xfer_set_frames(xfer, 1);
1909
		usbd_transfer_submit(xfer);
1910
1911
		umb_rxflush(sc);
1912
		break;
1913
	default:
1914
		DPRINTF("rx error: %s\n", usbd_errstr(status));
1915
1916
		/* disable throttling */
1917
		usbd_xfer_set_interval(xfer, 0);
1918
1919
		if (status != USB_ERR_CANCELLED) {
1920
			/* try to clear stall first */
1921
			usbd_xfer_set_stall(xfer);
1922
			usbd_xfer_set_frames(xfer, 0);
1923
			usbd_transfer_submit(xfer);
1924
			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1925
		}
1926
		else if (++sc->sc_rx_nerr > 100) {
1927
			log(LOG_ERR, "%s: too many rx errors, disabling\n",
1928
			    DEVNAM(sc));
1929
			umb_deactivate(sc->sc_dev);
1930
		}
1931
		break;
1932
	}
1933
}
1934
1935
static void
1936
umb_rxflush(struct umb_softc *sc)
1937
{
1938
	struct ifnet *ifp = GET_IFP(sc);
1939
	struct mbuf *m;
1940
1941
	mtx_assert(&sc->sc_mutex, MA_OWNED);
1942
1943
	for (;;) {
1944
		_IF_DEQUEUE(&sc->sc_rx_queue, m);
1945
		if (m == NULL)
1946
			break;
1947
1948
		/*
1949
		 * The USB xfer has been resubmitted so its safe to unlock now.
1950
		 */
1951
		mtx_unlock(&sc->sc_mutex);
1952
		CURVNET_SET_QUIET(vnet0);
1953
		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
1954
			ifp->if_input(ifp, m);
1955
		else
1956
			m_freem(m);
1957
		CURVNET_RESTORE();
1958
		mtx_lock(&sc->sc_mutex);
1959
	}
1960
}
1961
1962
static int
1963
umb_encap(struct umb_softc *sc, struct mbuf *m, struct usb_xfer *xfer)
1964
{
1965
	struct ncm_header16 *hdr;
1966
	struct ncm_pointer16 *ptr;
1967
	int	 len;
1968
1969
	KASSERT(sc->sc_tx_m == NULL,
1970
			("Assertion failed in umb_encap()"));
1971
1972
	/* All size constraints have been validated by the caller! */
1973
	hdr = (struct ncm_header16 *)sc->sc_tx_buf;
1974
	ptr = (struct ncm_pointer16 *)(hdr + 1);
1975
1976
	USETDW(hdr->dwSignature, NCM_HDR16_SIG);
1977
	USETW(hdr->wHeaderLength, sizeof (*hdr));
1978
	USETW(hdr->wSequence, sc->sc_tx_seq);
1979
	sc->sc_tx_seq++;
1980
	USETW(hdr->wNdpIndex, sizeof (*hdr));
1981
1982
	len = m->m_pkthdr.len;
1983
	USETDW(ptr->dwSignature, MBIM_NCM_NTH16_SIG(umb_session_id));
1984
	USETW(ptr->wLength, sizeof (*ptr));
1985
	USETW(ptr->wNextNdpIndex, 0);
1986
	USETW(ptr->dgram[0].wDatagramIndex, MBIM_HDR16_LEN);
1987
	USETW(ptr->dgram[0].wDatagramLen, len);
1988
	USETW(ptr->dgram[1].wDatagramIndex, 0);
1989
	USETW(ptr->dgram[1].wDatagramLen, 0);
1990
1991
	KASSERT(len + MBIM_HDR16_LEN <= sc->sc_tx_bufsz,
1992
			("Assertion failed in umb_encap()"));
1993
	m_copydata(m, 0, len, (char *)(ptr + 1));
1994
	sc->sc_tx_m = m;
1995
	len += MBIM_HDR16_LEN;
1996
	USETW(hdr->wBlockLength, len);
1997
1998
	usbd_xfer_set_frame_data(xfer, 0, sc->sc_tx_buf, len);
1999
	usbd_xfer_set_interval(xfer, 0);
2000
	usbd_xfer_set_frames(xfer, 1);
2001
2002
	DPRINTFN(3, "%s: encap %d bytes\n", DEVNAM(sc), len);
2003
	DDUMPN(5, sc->sc_tx_buf, len);
2004
	return 0;
2005
}
2006
2007
static void
2008
umb_txeof(struct usb_xfer *xfer, usb_error_t status)
2009
{
2010
	struct umb_softc *sc = usbd_xfer_softc(xfer);
2011
	struct ifnet *ifp = GET_IFP(sc);
2012
	struct mbuf *m;
2013
2014
	DPRINTF("%s(%u) state=%u\n", __func__, status, USB_GET_STATE(xfer));
2015
2016
	mtx_assert(&sc->sc_mutex, MA_OWNED);
2017
2018
	switch (USB_GET_STATE(xfer)) {
2019
	case USB_ST_TRANSFERRED:
2020
		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2021
		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2022
2023
		umb_txflush(sc);
2024
2025
		/* fall through */
2026
	case USB_ST_SETUP:
2027
tr_setup:
2028
		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
2029
			break;
2030
2031
		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
2032
		if (m == NULL)
2033
			break;
2034
2035
		if (umb_encap(sc, m, xfer)) {
2036
			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2037
			umb_txflush(sc);
2038
			break;
2039
		}
2040
2041
		BPF_MTAP(ifp, m);
2042
2043
		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
2044
		usbd_transfer_submit(xfer);
2045
2046
		break;
2047
2048
	default:
2049
		umb_txflush(sc);
2050
2051
		/* count output errors */
2052
		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2053
		DPRINTF("tx error: %s\n",
2054
				usbd_errstr(status));
2055
2056
		if (status != USB_ERR_CANCELLED) {
2057
			/* try to clear stall first */
2058
			usbd_xfer_set_stall(xfer);
2059
			goto tr_setup;
2060
		}
2061
		break;
2062
	}
2063
}
2064
2065
static void
2066
umb_txflush(struct umb_softc *sc)
2067
{
2068
	mtx_assert(&sc->sc_mutex, MA_OWNED);
2069
2070
	if (sc->sc_tx_m != NULL) {
2071
		m_freem(sc->sc_tx_m);
2072
		sc->sc_tx_m = NULL;
2073
	}
2074
}
2075
2076
static void
2077
umb_decap(struct umb_softc *sc, struct usb_xfer *xfer, int frame)
2078
{
2079
	struct ifnet *ifp = GET_IFP(sc);
2080
	char *buf;
2081
	int len;
2082
	char	*dp;
2083
	struct ncm_header16 *hdr16;
2084
	struct ncm_header32 *hdr32;
2085
	struct ncm_pointer16 *ptr16;
2086
	struct ncm_pointer16_dgram *dgram16;
2087
	struct ncm_pointer32_dgram *dgram32;
2088
	uint32_t hsig, psig;
2089
	int	 hlen, blen;
2090
	int	 ptrlen, ptroff, dgentryoff;
2091
	uint32_t doff, dlen;
2092
	struct mbuf *m;
2093
2094
	usbd_xfer_frame_data(xfer, frame, (void **)&buf, &len);
2095
	DPRINTFN(4, "recv %d bytes\n", len);
2096
	DDUMPN(5, buf, len);
2097
	if (len < sizeof (*hdr16))
2098
		goto toosmall;
2099
2100
	hdr16 = (struct ncm_header16 *)buf;
2101
	hsig = UGETDW(hdr16->dwSignature);
2102
	hlen = UGETW(hdr16->wHeaderLength);
2103
	if (len < hlen)
2104
		goto toosmall;
2105
	if (len > sc->sc_rx_bufsz) {
2106
		DPRINTF("packet too large (%d)\n", len);
2107
		goto fail;
2108
	}
2109
	switch (hsig) {
2110
	case NCM_HDR16_SIG:
2111
		blen = UGETW(hdr16->wBlockLength);
2112
		ptroff = UGETW(hdr16->wNdpIndex);
2113
		if (hlen != sizeof (*hdr16)) {
2114
			DPRINTF("%s: bad header len %d for NTH16 (exp %zu)\n",
2115
			    DEVNAM(sc), hlen, sizeof (*hdr16));
2116
			goto fail;
2117
		}
2118
		break;
2119
	case NCM_HDR32_SIG:
2120
		hdr32 = (struct ncm_header32 *)hdr16;
2121
		blen = UGETDW(hdr32->dwBlockLength);
2122
		ptroff = UGETDW(hdr32->dwNdpIndex);
2123
		if (hlen != sizeof (*hdr32)) {
2124
			DPRINTF("%s: bad header len %d for NTH32 (exp %zu)\n",
2125
			    DEVNAM(sc), hlen, sizeof (*hdr32));
2126
			goto fail;
2127
		}
2128
		break;
2129
	default:
2130
		DPRINTF("%s: unsupported NCM header signature (0x%08x)\n",
2131
		    DEVNAM(sc), hsig);
2132
		goto fail;
2133
	}
2134
	if (len < blen) {
2135
		DPRINTF("%s: bad NTB len (%d) for %d bytes of data\n",
2136
		    DEVNAM(sc), blen, len);
2137
		goto fail;
2138
	}
2139
2140
	ptr16 = (struct ncm_pointer16 *)(buf + ptroff);
2141
	psig = UGETDW(ptr16->dwSignature);
2142
	ptrlen = UGETW(ptr16->wLength);
2143
	if (len < ptrlen + ptroff)
2144
		goto toosmall;
2145
	if (!MBIM_NCM_NTH16_ISISG(psig) && !MBIM_NCM_NTH32_ISISG(psig)) {
2146
		DPRINTF("%s: unsupported NCM pointer signature (0x%08x)\n",
2147
		    DEVNAM(sc), psig);
2148
		goto fail;
2149
	}
2150
2151
	switch (hsig) {
2152
	case NCM_HDR16_SIG:
2153
		dgentryoff = offsetof(struct ncm_pointer16, dgram);
2154
		break;
2155
	case NCM_HDR32_SIG:
2156
		dgentryoff = offsetof(struct ncm_pointer32, dgram);
2157
		break;
2158
	default:
2159
		goto fail;
2160
	}
2161
2162
	while (dgentryoff < ptrlen) {
2163
		switch (hsig) {
2164
		case NCM_HDR16_SIG:
2165
			if (ptroff + dgentryoff < sizeof (*dgram16))
2166
				goto done;
2167
			dgram16 = (struct ncm_pointer16_dgram *)
2168
			    (buf + ptroff + dgentryoff);
2169
			dgentryoff += sizeof (*dgram16);
2170
			dlen = UGETW(dgram16->wDatagramLen);
2171
			doff = UGETW(dgram16->wDatagramIndex);
2172
			break;
2173
		case NCM_HDR32_SIG:
2174
			if (ptroff + dgentryoff < sizeof (*dgram32))
2175
				goto done;
2176
			dgram32 = (struct ncm_pointer32_dgram *)
2177
			    (buf + ptroff + dgentryoff);
2178
			dgentryoff += sizeof (*dgram32);
2179
			dlen = UGETDW(dgram32->dwDatagramLen);
2180
			doff = UGETDW(dgram32->dwDatagramIndex);
2181
			break;
2182
		default:
2183
			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2184
			goto done;
2185
		}
2186
2187
		/* Terminating zero entry */
2188
		if (dlen == 0 || doff == 0)
2189
			break;
2190
		if (len < dlen + doff) {
2191
			/* Skip giant datagram but continue processing */
2192
			DPRINTF("%s: datagram too large (%d @ off %d)\n",
2193
			    DEVNAM(sc), dlen, doff);
2194
			continue;
2195
		}
2196
2197
		dp = buf + doff;
2198
		DPRINTFN(3, "%s: decap %d bytes\n", DEVNAM(sc), dlen);
2199
		m = m_devget(dp, dlen, 0, ifp, NULL);
2200
		if (m == NULL) {
2201
			if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2202
			continue;
2203
		}
2204
2205
		/* enqueue for later when the lock can be released */
2206
		_IF_ENQUEUE(&sc->sc_rx_queue, m);
2207
2208
		if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
2209
2210
	}
2211
done:
2212
	sc->sc_rx_nerr = 0;
2213
	return;
2214
toosmall:
2215
	DPRINTF("%s: packet too small (%d)\n", DEVNAM(sc), len);
2216
fail:
2217
	if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2218
}
2219
2220
static usb_error_t
2221
umb_send_encap_command(struct umb_softc *sc, void *data, int len)
2222
{
2223
	usb_device_request_t req;
2224
2225
	if (len > sc->sc_ctrl_len)
2226
		return USB_ERR_INVAL;
2227
2228
	/* XXX FIXME: if (total len > sc->sc_ctrl_len) => must fragment */
2229
	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
2230
	req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
2231
	USETW(req.wValue, 0);
2232
	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2233
	USETW(req.wLength, len);
2234
	mtx_unlock(&sc->sc_mutex);
2235
	DELAY(umb_delay);
2236
	mtx_lock(&sc->sc_mutex);
2237
	return usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, data, 0,
2238
			NULL, umb_xfer_tout);
2239
}
2240
2241
static int
2242
umb_get_encap_response(struct umb_softc *sc, void *buf, int *len)
2243
{
2244
	usb_device_request_t req;
2245
	usb_error_t err;
2246
	uint16_t l = *len;
2247
2248
	req.bmRequestType = UT_READ_CLASS_INTERFACE;
2249
	req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
2250
	USETW(req.wValue, 0);
2251
	USETW(req.wIndex, sc->sc_ctrl_ifaceno);
2252
	USETW(req.wLength, l);
2253
	/* XXX FIXME: re-assemble fragments */
2254
2255
	mtx_unlock(&sc->sc_mutex);
2256
	DELAY(umb_delay);
2257
	mtx_lock(&sc->sc_mutex);
2258
	err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mutex, &req, buf,
2259
			USB_SHORT_XFER_OK, &l, umb_xfer_tout);
2260
	if (err == USB_ERR_NORMAL_COMPLETION) {
2261
		*len = l;
2262
		return 1;
2263
	}
2264
	DPRINTF("ctrl recv: %s\n", usbd_errstr(err));
2265
	return 0;
2266
}
2267
2268
static void
2269
umb_ctrl_msg(struct umb_softc *sc, uint32_t req, void *data, int len)
2270
{
2271
	struct ifnet *ifp = GET_IFP(sc);
2272
	uint32_t tid;
2273
	struct mbim_msghdr *hdr = data;
2274
	usb_error_t err;
2275
2276
	if (sc->sc_dying)
2277
		return;
2278
	if (len < sizeof (*hdr))
2279
		return;
2280
	tid = ++sc->sc_tid;
2281
2282
	hdr->type = htole32(req);
2283
	hdr->len = htole32(len);
2284
	hdr->tid = htole32(tid);
2285
2286
#ifdef UMB_DEBUG
2287
	if (umb_debug) {
2288
		const char *op, *str;
2289
		if (req == MBIM_COMMAND_MSG) {
2290
			struct mbim_h2f_cmd *c = data;
2291
			if (le32toh(c->op) == MBIM_CMDOP_SET)
2292
				op = "set";
2293
			else
2294
				op = "qry";
2295
			str = umb_cid2str(le32toh(c->cid));
2296
		} else {
2297
			op = "snd";
2298
			str = umb_request2str(req);
2299
		}
2300
		DPRINTF("-> %s %s (tid %u)\n", op, str, tid);
2301
	}
2302
#endif
2303
	err = umb_send_encap_command(sc, data, len);
2304
	if (err != USB_ERR_NORMAL_COMPLETION) {
2305
		if (ifp->if_flags & IFF_DEBUG)
2306
			log(LOG_ERR, "%s: send %s msg (tid %u) failed: %s\n",
2307
			    DEVNAM(sc), umb_request2str(req), tid,
2308
			    usbd_errstr(err));
2309
2310
		/* will affect other transactions, too */
2311
		usbd_transfer_stop(sc->sc_xfer[UMB_INTR_RX]);
2312
	} else {
2313
		DPRINTFN(2, "sent %s (tid %u)\n",
2314
		    umb_request2str(req), tid);
2315
		DDUMPN(3, data, len);
2316
	}
2317
	return;
2318
}
2319
2320
static void
2321
umb_open(struct umb_softc *sc)
2322
{
2323
	struct mbim_h2f_openmsg msg;
2324
2325
	memset(&msg, 0, sizeof (msg));
2326
	msg.maxlen = htole32(sc->sc_ctrl_len);
2327
	umb_ctrl_msg(sc, MBIM_OPEN_MSG, &msg, sizeof (msg));
2328
	return;
2329
}
2330
2331
static void
2332
umb_close(struct umb_softc *sc)
2333
{
2334
	struct mbim_h2f_closemsg msg;
2335
2336
	memset(&msg, 0, sizeof (msg));
2337
	umb_ctrl_msg(sc, MBIM_CLOSE_MSG, &msg, sizeof (msg));
2338
}
2339
2340
static int
2341
umb_setpin(struct umb_softc *sc, int op, int is_puk, void *pin, int pinlen,
2342
    void *newpin, int newpinlen)
2343
{
2344
	struct mbim_cid_pin cp;
2345
	int	 off;
2346
2347
	if (pinlen == 0)
2348
		return 0;
2349
	if (pinlen < 0 || pinlen > MBIM_PIN_MAXLEN ||
2350
	    newpinlen < 0 || newpinlen > MBIM_PIN_MAXLEN ||
2351
	    op < 0 || op > MBIM_PIN_OP_CHANGE ||
2352
	    (is_puk && op != MBIM_PIN_OP_ENTER))
2353
		return EINVAL;
2354
2355
	memset(&cp, 0, sizeof (cp));
2356
	cp.type = htole32(is_puk ? MBIM_PIN_TYPE_PUK1 : MBIM_PIN_TYPE_PIN1);
2357
2358
	off = offsetof(struct mbim_cid_pin, data);
2359
	if (!umb_addstr(&cp, sizeof (cp), &off, pin, pinlen,
2360
	    &cp.pin_offs, &cp.pin_size))
2361
		return EINVAL;
2362
2363
	cp.op  = htole32(op);
2364
	if (newpinlen) {
2365
		if (!umb_addstr(&cp, sizeof (cp), &off, newpin, newpinlen,
2366
		    &cp.newpin_offs, &cp.newpin_size))
2367
			return EINVAL;
2368
	} else {
2369
		if ((op == MBIM_PIN_OP_CHANGE) || is_puk)
2370
			return EINVAL;
2371
		if (!umb_addstr(&cp, sizeof (cp), &off, NULL, 0,
2372
		    &cp.newpin_offs, &cp.newpin_size))
2373
			return EINVAL;
2374
	}
2375
	mtx_lock(&sc->sc_mutex);
2376
	umb_cmd(sc, MBIM_CID_PIN, MBIM_CMDOP_SET, &cp, off);
2377
	mtx_unlock(&sc->sc_mutex);
2378
	return 0;
2379
}
2380
2381
static void
2382
umb_setdataclass(struct umb_softc *sc)
2383
{
2384
	struct mbim_cid_registration_state rs;
2385
	uint32_t	 classes;
2386
2387
	if (sc->sc_info.supportedclasses == MBIM_DATACLASS_NONE)
2388
		return;
2389
2390
	memset(&rs, 0, sizeof (rs));
2391
	rs.regaction = htole32(MBIM_REGACTION_AUTOMATIC);
2392
	classes = sc->sc_info.supportedclasses;
2393
	if (sc->sc_info.preferredclasses != MBIM_DATACLASS_NONE)
2394
		classes &= sc->sc_info.preferredclasses;
2395
	rs.data_class = htole32(classes);
2396
	mtx_lock(&sc->sc_mutex);
2397
	umb_cmd(sc, MBIM_CID_REGISTER_STATE, MBIM_CMDOP_SET, &rs, sizeof (rs));
2398
	mtx_unlock(&sc->sc_mutex);
2399
}
2400
2401
static void
2402
umb_radio(struct umb_softc *sc, int on)
2403
{
2404
	struct mbim_cid_radio_state s;
2405
2406
	DPRINTF("set radio %s\n", on ? "on" : "off");
2407
	memset(&s, 0, sizeof (s));
2408
	s.state = htole32(on ? MBIM_RADIO_STATE_ON : MBIM_RADIO_STATE_OFF);
2409
	umb_cmd(sc, MBIM_CID_RADIO_STATE, MBIM_CMDOP_SET, &s, sizeof (s));
2410
}
2411
2412
static void
2413
umb_allocate_cid(struct umb_softc *sc)
2414
{
2415
	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2416
	    umb_qmi_alloc_cid, sizeof (umb_qmi_alloc_cid), umb_uuid_qmi_mbim);
2417
}
2418
2419
static void
2420
umb_send_fcc_auth(struct umb_softc *sc)
2421
{
2422
	uint8_t	 fccauth[sizeof (umb_qmi_fcc_auth)];
2423
2424
	if (sc->sc_cid == -1) {
2425
		DPRINTF("missing CID, cannot send FCC auth\n");
2426
		umb_allocate_cid(sc);
2427
		return;
2428
	}
2429
	memcpy(fccauth, umb_qmi_fcc_auth, sizeof (fccauth));
2430
	fccauth[UMB_QMI_CID_OFFS] = sc->sc_cid;
2431
	umb_cmd1(sc, MBIM_CID_DEVICE_CAPS, MBIM_CMDOP_SET,
2432
	    fccauth, sizeof (fccauth), umb_uuid_qmi_mbim);
2433
}
2434
2435
static void
2436
umb_packet_service(struct umb_softc *sc, int attach)
2437
{
2438
	struct mbim_cid_packet_service	s;
2439
2440
	DPRINTF("%s packet service\n",
2441
	    attach ? "attach" : "detach");
2442
	memset(&s, 0, sizeof (s));
2443
	s.action = htole32(attach ?
2444
	    MBIM_PKTSERVICE_ACTION_ATTACH : MBIM_PKTSERVICE_ACTION_DETACH);
2445
	umb_cmd(sc, MBIM_CID_PACKET_SERVICE, MBIM_CMDOP_SET, &s, sizeof (s));
2446
}
2447
2448
static void
2449
umb_connect(struct umb_softc *sc)
2450
{
2451
	struct ifnet *ifp = GET_IFP(sc);
2452
2453
	if (sc->sc_info.regstate == MBIM_REGSTATE_ROAMING && !sc->sc_roaming) {
2454
		log(LOG_INFO, "%s: connection disabled in roaming network\n",
2455
		    DEVNAM(sc));
2456
		return;
2457
	}
2458
	if (ifp->if_flags & IFF_DEBUG)
2459
		log(LOG_DEBUG, "%s: connecting ...\n", DEVNAM(sc));
2460
	umb_send_connect(sc, MBIM_CONNECT_ACTIVATE);
2461
}
2462
2463
static void
2464
umb_disconnect(struct umb_softc *sc)
2465
{
2466
	struct ifnet *ifp = GET_IFP(sc);
2467
2468
	if (ifp->if_flags & IFF_DEBUG)
2469
		log(LOG_DEBUG, "%s: disconnecting ...\n", DEVNAM(sc));
2470
	umb_send_connect(sc, MBIM_CONNECT_DEACTIVATE);
2471
}
2472
2473
static void
2474
umb_send_connect(struct umb_softc *sc, int command)
2475
{
2476
	struct mbim_cid_connect *c;
2477
	int	 off;
2478
2479
	/* Too large for the stack */
2480
	mtx_unlock(&sc->sc_mutex);
2481
	c = malloc(sizeof (*c), M_MBIM_CID_CONNECT, M_WAITOK | M_ZERO);
2482
	mtx_lock(&sc->sc_mutex);
2483
	c->sessionid = htole32(umb_session_id);
2484
	c->command = htole32(command);
2485
	off = offsetof(struct mbim_cid_connect, data);
2486
	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.apn,
2487
	    sc->sc_info.apnlen, &c->access_offs, &c->access_size))
2488
		goto done;
2489
	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.username,
2490
	    sc->sc_info.usernamelen, &c->user_offs, &c->user_size))
2491
		goto done;
2492
	if (!umb_addstr(c, sizeof (*c), &off, sc->sc_info.password,
2493
	    sc->sc_info.passwordlen, &c->passwd_offs, &c->passwd_size))
2494
		goto done;
2495
	c->authprot = htole32(MBIM_AUTHPROT_NONE);
2496
	c->compression = htole32(MBIM_COMPRESSION_NONE);
2497
	c->iptype = htole32(MBIM_CONTEXT_IPTYPE_IPV4);
2498
	memcpy(c->context, umb_uuid_context_internet, sizeof (c->context));
2499
	umb_cmd(sc, MBIM_CID_CONNECT, MBIM_CMDOP_SET, c, off);
2500
done:
2501
	free(c, M_MBIM_CID_CONNECT);
2502
	return;
2503
}
2504
2505
static void
2506
umb_qry_ipconfig(struct umb_softc *sc)
2507
{
2508
	struct mbim_cid_ip_configuration_info ipc;
2509
2510
	memset(&ipc, 0, sizeof (ipc));
2511
	ipc.sessionid = htole32(umb_session_id);
2512
	umb_cmd(sc, MBIM_CID_IP_CONFIGURATION, MBIM_CMDOP_QRY,
2513
	    &ipc, sizeof (ipc));
2514
}
2515
2516
static void
2517
umb_cmd(struct umb_softc *sc, int cid, int op, const void *data, int len)
2518
{
2519
	umb_cmd1(sc, cid, op, data, len, umb_uuid_basic_connect);
2520
}
2521
2522
static void
2523
umb_cmd1(struct umb_softc *sc, int cid, int op, const void *data, int len,
2524
    uint8_t *uuid)
2525
{
2526
	struct mbim_h2f_cmd *cmd;
2527
	int	totlen;
2528
2529
	/* XXX FIXME support sending fragments */
2530
	if (sizeof (*cmd) + len > sc->sc_ctrl_len) {
2531
		DPRINTF("set %s msg too long: cannot send\n",
2532
		    umb_cid2str(cid));
2533
		return;
2534
	}
2535
	cmd = sc->sc_ctrl_msg;
2536
	memset(cmd, 0, sizeof (*cmd));
2537
	cmd->frag.nfrag = htole32(1);
2538
	memcpy(cmd->devid, uuid, sizeof (cmd->devid));
2539
	cmd->cid = htole32(cid);
2540
	cmd->op = htole32(op);
2541
	cmd->infolen = htole32(len);
2542
	totlen = sizeof (*cmd);
2543
	if (len > 0) {
2544
		memcpy(cmd + 1, data, len);
2545
		totlen += len;
2546
	}
2547
	umb_ctrl_msg(sc, MBIM_COMMAND_MSG, cmd, totlen);
2548
}
2549
2550
static void
2551
umb_command_done(struct umb_softc *sc, void *data, int len)
2552
{
2553
	struct mbim_f2h_cmddone *cmd = data;
2554
	struct ifnet *ifp = GET_IFP(sc);
2555
	uint32_t status;
2556
	uint32_t cid;
2557
	uint32_t infolen;
2558
	int	 qmimsg = 0;
2559
2560
	if (len < sizeof (*cmd)) {
2561
		DPRINTF("discard short %s message\n",
2562
		    umb_request2str(le32toh(cmd->hdr.type)));
2563
		return;
2564
	}
2565
	cid = le32toh(cmd->cid);
2566
	if (memcmp(cmd->devid, umb_uuid_basic_connect, sizeof (cmd->devid))) {
2567
		if (memcmp(cmd->devid, umb_uuid_qmi_mbim,
2568
		    sizeof (cmd->devid))) {
2569
			DPRINTF("discard %s message for other UUID '%s'\n",
2570
			    umb_request2str(le32toh(cmd->hdr.type)),
2571
			    umb_uuid2str(cmd->devid));
2572
			return;
2573
		} else
2574
			qmimsg = 1;
2575
	}
2576
2577
	status = le32toh(cmd->status);
2578
	switch (status) {
2579
	case MBIM_STATUS_SUCCESS:
2580
		break;
2581
	case MBIM_STATUS_NOT_INITIALIZED:
2582
		if (ifp->if_flags & IFF_DEBUG)
2583
			log(LOG_ERR, "%s: SIM not initialized (PIN missing)\n",
2584
			    DEVNAM(sc));
2585
		return;
2586
	case MBIM_STATUS_PIN_REQUIRED:
2587
		sc->sc_info.pin_state = UMB_PIN_REQUIRED;
2588
		/*FALLTHROUGH*/
2589
	default:
2590
		if (ifp->if_flags & IFF_DEBUG)
2591
			log(LOG_ERR, "%s: set/qry %s failed: %s\n", DEVNAM(sc),
2592
			    umb_cid2str(cid), umb_status2str(status));
2593
		return;
2594
	}
2595
2596
	infolen = le32toh(cmd->infolen);
2597
	if (len < sizeof (*cmd) + infolen) {
2598
		DPRINTF("discard truncated %s message (want %d, got %d)\n",
2599
		    umb_cid2str(cid),
2600
		    (int)sizeof (*cmd) + infolen, len);
2601
		return;
2602
	}
2603
	if (qmimsg) {
2604
		if (sc->sc_flags & UMBFLG_FCC_AUTH_REQUIRED)
2605
			umb_decode_qmi(sc, cmd->info, infolen);
2606
	} else {
2607
		DPRINTFN(2, "set/qry %s done\n",
2608
		    umb_cid2str(cid));
2609
		umb_decode_cid(sc, cid, cmd->info, infolen);
2610
	}
2611
}
2612
2613
static void
2614
umb_decode_cid(struct umb_softc *sc, uint32_t cid, void *data, int len)
2615
{
2616
	int	 ok = 1;
2617
2618
	switch (cid) {
2619
	case MBIM_CID_DEVICE_CAPS:
2620
		ok = umb_decode_devices_caps(sc, data, len);
2621
		break;
2622
	case MBIM_CID_SUBSCRIBER_READY_STATUS:
2623
		ok = umb_decode_subscriber_status(sc, data, len);
2624
		break;
2625
	case MBIM_CID_RADIO_STATE:
2626
		ok = umb_decode_radio_state(sc, data, len);
2627
		break;
2628
	case MBIM_CID_PIN:
2629
		ok = umb_decode_pin(sc, data, len);
2630
		break;
2631
	case MBIM_CID_REGISTER_STATE:
2632
		ok = umb_decode_register_state(sc, data, len);
2633
		break;
2634
	case MBIM_CID_PACKET_SERVICE:
2635
		ok = umb_decode_packet_service(sc, data, len);
2636
		break;
2637
	case MBIM_CID_SIGNAL_STATE:
2638
		ok = umb_decode_signal_state(sc, data, len);
2639
		break;
2640
	case MBIM_CID_CONNECT:
2641
		ok = umb_decode_connect_info(sc, data, len);
2642
		break;
2643
	case MBIM_CID_IP_CONFIGURATION:
2644
		ok = umb_decode_ip_configuration(sc, data, len);
2645
		break;
2646
	default:
2647
		/*
2648
		 * Note: the above list is incomplete and only contains
2649
		 *	mandatory CIDs from the BASIC_CONNECT set.
2650
		 *	So alternate values are not unusual.
2651
		 */
2652
		DPRINTFN(4, "ignore %s\n", umb_cid2str(cid));
2653
		break;
2654
	}
2655
	if (!ok)
2656
		DPRINTF("discard %s with bad info length %d\n",
2657
		    umb_cid2str(cid), len);
2658
	return;
2659
}
2660
2661
static void
2662
umb_decode_qmi(struct umb_softc *sc, uint8_t *data, int len)
2663
{
2664
	uint8_t	srv;
2665
	uint16_t msg, tlvlen;
2666
	uint32_t val;
2667
2668
#define UMB_QMI_QMUXLEN		6
2669
	if (len < UMB_QMI_QMUXLEN)
2670
		goto tooshort;
2671
2672
	srv = data[4];
2673
	data += UMB_QMI_QMUXLEN;
2674
	len -= UMB_QMI_QMUXLEN;
2675
2676
#define UMB_GET16(p)	((uint16_t)*p | (uint16_t)*(p + 1) << 8)
2677
#define UMB_GET32(p)	((uint32_t)*p | (uint32_t)*(p + 1) << 8 | \
2678
			    (uint32_t)*(p + 2) << 16 |(uint32_t)*(p + 3) << 24)
2679
	switch (srv) {
2680
	case 0:	/* ctl */
2681
#define UMB_QMI_CTLLEN		6
2682
		if (len < UMB_QMI_CTLLEN)
2683
			goto tooshort;
2684
		msg = UMB_GET16(&data[2]);
2685
		tlvlen = UMB_GET16(&data[4]);
2686
		data += UMB_QMI_CTLLEN;
2687
		len -= UMB_QMI_CTLLEN;
2688
		break;
2689
	case 2:	/* dms  */
2690
#define UMB_QMI_DMSLEN		7
2691
		if (len < UMB_QMI_DMSLEN)
2692
			goto tooshort;
2693
		msg = UMB_GET16(&data[3]);
2694
		tlvlen = UMB_GET16(&data[5]);
2695
		data += UMB_QMI_DMSLEN;
2696
		len -= UMB_QMI_DMSLEN;
2697
		break;
2698
	default:
2699
		DPRINTF("discard QMI message for unknown service type %d\n",
2700
		    srv);
2701
		return;
2702
	}
2703
2704
	if (len < tlvlen)
2705
		goto tooshort;
2706
2707
#define UMB_QMI_TLVLEN		3
2708
	while (len > 0) {
2709
		if (len < UMB_QMI_TLVLEN)
2710
			goto tooshort;
2711
		tlvlen = UMB_GET16(&data[1]);
2712
		if (len < UMB_QMI_TLVLEN + tlvlen)
2713
			goto tooshort;
2714
		switch (data[0]) {
2715
		case 1:	/* allocation info */
2716
			if (msg == 0x0022) {	/* Allocate CID */
2717
				if (tlvlen != 2 || data[3] != 2) /* dms */
2718
					break;
2719
				sc->sc_cid = data[4];
2720
				DPRINTF("QMI CID %d allocated\n",
2721
				    sc->sc_cid);
2722
				umb_newstate(sc, UMB_S_CID, UMB_NS_DONT_DROP);
2723
			}
2724
			break;
2725
		case 2:	/* response */
2726
			if (tlvlen != sizeof (val))
2727
				break;
2728
			val = UMB_GET32(&data[3]);
2729
			switch (msg) {
2730
			case 0x0022:	/* Allocate CID */
2731
				if (val != 0) {
2732
					log(LOG_ERR, "%s: allocation of QMI CID"
2733
					    " failed, error 0x%x\n", DEVNAM(sc),
2734
					    val);
2735
					/* XXX how to proceed? */
2736
					return;
2737
				}
2738
				break;
2739
			case 0x555f:	/* Send FCC Authentication */
2740
				if (val == 0)
2741
					DPRINTF("%s: send FCC "
2742
					    "Authentication succeeded\n",
2743
					    DEVNAM(sc));
2744
				else if (val == 0x001a0001)
2745
					DPRINTF("%s: FCC Authentication "
2746
					    "not required\n", DEVNAM(sc));
2747
				else
2748
					log(LOG_INFO, "%s: send FCC "
2749
					    "Authentication failed, "
2750
					    "error 0x%x\n", DEVNAM(sc), val);
2751
2752
				/* FCC Auth is needed only once after power-on*/
2753
				sc->sc_flags &= ~UMBFLG_FCC_AUTH_REQUIRED;
2754
2755
				/* Try to proceed anyway */
2756
				DPRINTF("init: turning radio on ...\n");
2757
				umb_radio(sc, 1);
2758
				break;
2759
			default:
2760
				break;
2761
			}
2762
			break;
2763
		default:
2764
			break;
2765
		}
2766
		data += UMB_QMI_TLVLEN + tlvlen;
2767
		len -= UMB_QMI_TLVLEN + tlvlen;
2768
	}
2769
	return;
2770
2771
tooshort:
2772
	DPRINTF("discard short QMI message\n");
2773
	return;
2774
}
2775
2776
static void
2777
umb_intr(struct usb_xfer *xfer, usb_error_t status)
2778
{
2779
	struct umb_softc *sc = usbd_xfer_softc(xfer);
2780
	struct usb_cdc_notification notification;
2781
	struct usb_page_cache *pc;
2782
	struct ifnet *ifp = GET_IFP(sc);
2783
	int	 total_len;
2784
2785
	mtx_assert(&sc->sc_mutex, MA_OWNED);
2786
2787
	/* FIXME use actlen or total_len? */
2788
	usbd_xfer_status(xfer, &total_len, NULL, NULL, NULL);
2789
2790
	switch (USB_GET_STATE(xfer)) {
2791
	case USB_ST_TRANSFERRED:
2792
		DPRINTF("Received %d bytes\n", total_len);
2793
2794
		if (total_len < UCDC_NOTIFICATION_LENGTH) {
2795
			DPRINTF("short notification (%d<%d)\n",
2796
					total_len, UCDC_NOTIFICATION_LENGTH);
2797
			return;
2798
		}
2799
2800
		pc = usbd_xfer_get_frame(xfer, 0);
2801
		usbd_copy_out(pc, 0, &notification, sizeof (notification));
2802
2803
		if (notification.bmRequestType != UCDC_NOTIFICATION) {
2804
			DPRINTF("unexpected notification (type=0x%02x)\n",
2805
					notification.bmRequestType);
2806
			return;
2807
		}
2808
2809
		switch (notification.bNotification) {
2810
		case UCDC_N_NETWORK_CONNECTION:
2811
			if (ifp->if_flags & IFF_DEBUG)
2812
				log(LOG_DEBUG, "%s: network %sconnected\n",
2813
						DEVNAM(sc),
2814
						UGETW(notification.wValue)
2815
						? "" : "dis");
2816
			break;
2817
		case UCDC_N_RESPONSE_AVAILABLE:
2818
			DPRINTFN(2, "umb_intr: response available\n");
2819
			++sc->sc_nresp;
2820
			umb_add_task(sc, umb_get_response_task,
2821
					&sc->sc_proc_get_response_task[0].hdr,
2822
					&sc->sc_proc_get_response_task[1].hdr,
2823
					0);
2824
			break;
2825
		case UCDC_N_CONNECTION_SPEED_CHANGE:
2826
			DPRINTFN(2, "umb_intr: connection speed changed\n");
2827
			break;
2828
		default:
2829
			DPRINTF("unexpected notification (0x%02x)\n",
2830
					notification.bNotification);
2831
			break;
2832
		}
2833
		/* fallthrough */
2834
	case USB_ST_SETUP:
2835
tr_setup:
2836
		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
2837
		usbd_transfer_submit(xfer);
2838
		break;
2839
	default:
2840
		if (status != USB_ERR_CANCELLED) {
2841
			/* start clear stall */
2842
			usbd_xfer_set_stall(xfer);
2843
			goto tr_setup;
2844
		}
2845
		break;
2846
	}
2847
}
2848
2849
/*
2850
 * Diagnostic routines
2851
 */
2852
static char *
2853
umb_ntop(struct sockaddr *sa)
2854
{
2855
#define NUMBUFS		4
2856
	static char astr[NUMBUFS][INET_ADDRSTRLEN];
2857
	static unsigned nbuf = 0;
2858
	char	*s;
2859
2860
	s = astr[nbuf++];
2861
	if (nbuf >= NUMBUFS)
2862
		nbuf = 0;
2863
2864
	switch (sa->sa_family) {
2865
	case AF_INET:
2866
	default:
2867
		inet_ntop(AF_INET, &satosin(sa)->sin_addr, s, sizeof (astr[0]));
2868
		break;
2869
	case AF_INET6:
2870
		inet_ntop(AF_INET6, &satosin6(sa)->sin6_addr, s,
2871
		    sizeof (astr[0]));
2872
		break;
2873
	}
2874
	return s;
2875
}
2876
2877
#ifdef UMB_DEBUG
2878
static char *
2879
umb_uuid2str(uint8_t uuid[MBIM_UUID_LEN])
2880
{
2881
	static char uuidstr[2 * MBIM_UUID_LEN + 5];
2882
2883
#define UUID_BFMT	"%02X"
2884
#define UUID_SEP	"-"
2885
	snprintf(uuidstr, sizeof (uuidstr),
2886
	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_SEP
2887
	    UUID_BFMT UUID_BFMT UUID_SEP
2888
	    UUID_BFMT UUID_BFMT UUID_SEP
2889
	    UUID_BFMT UUID_BFMT UUID_SEP
2890
	    UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT UUID_BFMT,
2891
	    uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
2892
	    uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
2893
	    uuid[12], uuid[13], uuid[14], uuid[15]);
2894
	return uuidstr;
2895
}
2896
2897
static void
2898
umb_dump(void *buf, int len)
2899
{
2900
	int	 i = 0;
2901
	uint8_t	*c = buf;
2902
2903
	if (len == 0)
2904
		return;
2905
	while (i < len) {
2906
		if ((i % 16) == 0) {
2907
			if (i > 0)
2908
				log(LOG_DEBUG, "\n");
2909
			log(LOG_DEBUG, "%4d:  ", i);
2910
		}
2911
		log(LOG_DEBUG, " %02x", *c);
2912
		c++;
2913
		i++;
2914
	}
2915
	log(LOG_DEBUG, "\n");
2916
}
2917
#endif /* UMB_DEBUG */
2918
2919
DRIVER_MODULE(umb, uhub, umb_driver, NULL, NULL);
2920
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