View | Details | Raw Unified | Return to bug 263783
Collapse All | Expand All

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

Return to bug 263783