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

Collapse All | Expand All

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

Return to bug 263783