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

Collapse All | Expand All

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