mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-31 15:35:13 +08:00
🍕 Sync 2026-03-05 23:56:52
This commit is contained in:
1 parent
c2cf764a6f
commit
bc2ed3a2df
2803 files changed
+26
-1604317
No files matched your search
@@ -1,4 +1,4 @@
|
||||
## 适用于openwrt 23.05 及以上的分支.
|
||||
## 适用于openwrt 24.10 及以上的分支.
|
||||
## 所有插件都为网上收集的开源插件,感谢作者们的付出.
|
||||
|
||||
## 本仓库所有插件已编译IPK下载
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -1,131 +0,0 @@
|
||||
#B
|
||||
#
|
||||
# Copyright (C) 2013-2015 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=accel-ppp
|
||||
PKG_RELEASE:=1
|
||||
PKG_VERSION:=1.14.0
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=https://github.com/accel-ppp/accel-ppp.git
|
||||
PKG_SOURCE_VERSION:=048d31cb446879e0d1a1471b4ab99135a92bf289
|
||||
|
||||
PKG_MAINTAINER:=Konstantine Shevlakov <shevlakov@132lan.ru>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
#PKG_INSTALL:=1
|
||||
#PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_accel-ppp_$(BUILD_VARIANT)_ext_cer_id
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=accel-ppp VPN server
|
||||
DEPENDS:=+libpcre2 +libopenssl +libpthread +librt +libatomic +libucontext
|
||||
endef
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DKDIR=$(LINUX_DIR) \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DLOG_PGSQL=FALSE \
|
||||
-DSHAPER=TRUE \
|
||||
-DRADIUS=FALSE \
|
||||
-DNETSNMP=FALSE \
|
||||
-DLOG_FILE=TRUE \
|
||||
-DLIB_SUFFIX= \
|
||||
|
||||
ifeq ($(ARCH),$(filter $(ARCH), x86_64 i386))
|
||||
CMAKE_OPTIONS += \
|
||||
-DBUILD_IPOE_DRIVER=TRUE \
|
||||
-DBUILD_VLAN_MON_DRIVER=TRUE
|
||||
endif
|
||||
|
||||
|
||||
CMAKE_BINARY_DIR := $(PKG_BUILD_DIR)/build
|
||||
TARGET_CFLAGS += -I$(STAGING_DIR)/opt/include -D_GNU_SOURCE -g -O2 -Wno-incompatible-pointer-types
|
||||
TARGET_LDFLAGS += -lpthread -latomic -lucontext
|
||||
|
||||
define KernelPackage/$(PKG_NAME)-ipoe
|
||||
SUBMENU:= Accel-PPP kernel modules
|
||||
TITLE:=Accel-PPP IPoE kernel module
|
||||
DEPENDS:=+accel-ppp
|
||||
FILES:=$(CMAKE_BINARY_DIR)/drivers/ipoe/driver/ipoe.ko
|
||||
AUTOLOAD:=$(call AutoProbe,ipoe)
|
||||
endef
|
||||
|
||||
define KernelPackage/$(PKG_NAME)-vlan-mon
|
||||
SUBMENU:=Accel-PPP kernel modules
|
||||
TITLE:=Accel-PPP vlan-mon kernel module
|
||||
DEPENDS:=+accel-ppp
|
||||
FILES:=$(CMAKE_BINARY_DIR)/drivers/vlan_mon/driver/vlan_mon.ko
|
||||
AUTOLOAD:=$(call AutoProbe,vlan_mon)
|
||||
endef
|
||||
|
||||
|
||||
define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_DIR) \
|
||||
$(1)/usr/sbin \
|
||||
$(1)/usr/bin \
|
||||
$(1)/usr/lib \
|
||||
$(1)/usr/lib/accel-ppp \
|
||||
$(1)/usr/share/accel-ppp \
|
||||
$(1)/usr/share/accel-ppp/radius \
|
||||
$(1)/usr/share/accel-ppp/l2tp \
|
||||
$(1)/etc/init.d \
|
||||
$(1)/etc/accel-ppp
|
||||
|
||||
$(INSTALL_BIN) \
|
||||
$(PKG_INSTALL_DIR)/usr/sbin/accel-pppd \
|
||||
$(1)/usr/sbin/
|
||||
|
||||
$(INSTALL_BIN) \
|
||||
$(PKG_INSTALL_DIR)/usr/bin/accel-cmd \
|
||||
$(1)/usr/bin/
|
||||
|
||||
$(INSTALL_BIN) \
|
||||
$(PKG_INSTALL_DIR)/usr/lib/accel-ppp/*.so \
|
||||
$(1)/usr/lib/accel-ppp/
|
||||
|
||||
$(INSTALL_DATA) \
|
||||
$(PKG_INSTALL_DIR)/usr/share/accel-ppp/l2tp/dictionary.* \
|
||||
$(1)/usr/share/accel-ppp/l2tp/
|
||||
|
||||
$(INSTALL_BIN) \
|
||||
files/accel-ppp.init \
|
||||
$(1)/etc/init.d/accel-ppp
|
||||
|
||||
$(INSTALL_DATA) \
|
||||
files/accel-ppp.conf \
|
||||
$(1)/etc/accel-ppp
|
||||
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/postinst
|
||||
for l in $$(ls -1 /usr/lib/accel-ppp/); do
|
||||
ln -s /usr/lib/accel-ppp/$$l /usr/lib/
|
||||
done
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/prerm
|
||||
for l in $$(ls -1 /usr/lib/accel-ppp/); do
|
||||
rm -f /usr/lib/$$l
|
||||
done
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,$(PKG_NAME)))
|
||||
ifeq ($(ARCH),$(filter $(ARCH), x86_64 i386))
|
||||
$(eval $(call KernelPackage,$(PKG_NAME)-ipoe))
|
||||
$(eval $(call KernelPackage,$(PKG_NAME)-vlan-mon))
|
||||
endif
|
||||
@@ -1,3 +0,0 @@
|
||||
# openwrt-accel-ppp
|
||||
ACCEL-PPP is a high performance VPN server application for linux.
|
||||
OpenWrt package
|
||||
@@ -1,337 +0,0 @@
|
||||
[modules]
|
||||
connlimit
|
||||
log_file
|
||||
#log_syslog
|
||||
#log_tcp
|
||||
#log_pgsql
|
||||
|
||||
pptp
|
||||
# L2TP not Work!
|
||||
#l2tp
|
||||
sstp
|
||||
#pppoe
|
||||
#ipoe
|
||||
|
||||
auth_mschap_v2
|
||||
#auth_mschap_v1
|
||||
#auth_chap_md5
|
||||
#auth_pap
|
||||
|
||||
chap-secrets
|
||||
|
||||
ippool
|
||||
|
||||
pppd_compat
|
||||
|
||||
#shaper
|
||||
#net-snmp
|
||||
#logwtmp
|
||||
|
||||
#ipv6_nd
|
||||
#ipv6_dhcp
|
||||
#ipv6pool
|
||||
|
||||
[core]
|
||||
log-error=/tmp/accel-ppp-core.log
|
||||
thread-count=4
|
||||
|
||||
[common]
|
||||
#single-session=replace
|
||||
#single-session-ignore-case=0
|
||||
#sid-case=upper
|
||||
#sid-source=seq
|
||||
#max-sessions=1000
|
||||
#max-starting=0
|
||||
#check-ip=0
|
||||
#nl-snd-buffer=32768
|
||||
#nl-rcv-buffer=1048576
|
||||
|
||||
[ppp]
|
||||
verbose=1
|
||||
min-mtu=1280
|
||||
mtu=1400
|
||||
mru=1400
|
||||
accomp=deny
|
||||
pcomp=deny
|
||||
#ccp=0
|
||||
mppe=require
|
||||
ipv4=require
|
||||
ipv6=deny
|
||||
ipv6-intf-id=0:0:0:1
|
||||
ipv6-peer-intf-id=0:0:0:2
|
||||
ipv6-accept-peer-intf-id=1
|
||||
lcp-echo-interval=20
|
||||
lcp-echo-failure=3
|
||||
lcp-echo-timeout=120
|
||||
unit-cache=1
|
||||
#unit-preallocate=1
|
||||
|
||||
[auth]
|
||||
#timeout=5
|
||||
#interval=0
|
||||
#max-failure=3
|
||||
#any-login=0
|
||||
#noauth=0
|
||||
#challenge-name=accel-ppp
|
||||
|
||||
[pptp]
|
||||
verbose=1
|
||||
#echo-interval=30
|
||||
ip-pool=pool3
|
||||
#ipv6-pool=pptp
|
||||
#ipv6-pool-delegate=pptp
|
||||
ifname=pptp%d
|
||||
|
||||
[pppoe]
|
||||
verbose=1
|
||||
#ac-name=xxx
|
||||
#service-name=yyy
|
||||
#pado-delay=0
|
||||
#pado-delay=0,100:100,200:200,-1:500
|
||||
called-sid=mac
|
||||
#tr101=1
|
||||
#padi-limit=0
|
||||
#ip-pool=pppoe
|
||||
#ipv6-pool=pppoe
|
||||
#ipv6-pool-delegate=pppoe
|
||||
#ifname=pppoe%d
|
||||
#sid-uppercase=0
|
||||
#vlan-mon=eth0,10-200
|
||||
#vlan-timeout=60
|
||||
#vlan-name=%I.%N
|
||||
#interface=eth1,padi-limit=1000
|
||||
interface=eth0
|
||||
|
||||
[l2tp]
|
||||
verbose=1
|
||||
#dictionary=/usr/local/share/accel-ppp/l2tp/dictionary
|
||||
#hello-interval=60
|
||||
#timeout=60
|
||||
#rtimeout=1
|
||||
#rtimeout-cap=16
|
||||
#retransmit=5
|
||||
#recv-window=16
|
||||
#host-name=accel-ppp
|
||||
#dir300_quirk=0
|
||||
#secret=
|
||||
#dataseq=allow
|
||||
#reorder-timeout=0
|
||||
#ip-pool=l2tp
|
||||
#ipv6-pool=l2tp
|
||||
#ipv6-pool-delegate=l2tp
|
||||
#ifname=l2tp%d
|
||||
|
||||
[sstp]
|
||||
verbose=2
|
||||
#cert-hash-proto=sha1,sha256
|
||||
#cert-hash-sha1=
|
||||
#cert-hash-sha256=
|
||||
#accept=ssl,proxy
|
||||
#ssl-protocol=tls1,tls1.1,tls1.2,tls1.3
|
||||
#ssl-dhparam=/etc/ssl/dhparam.pem
|
||||
#ssl-ecdh-curve=prime256v1
|
||||
#ssl-ciphers=DEFAULT
|
||||
#ssl-prefer-server-ciphers=0
|
||||
#ssl-ca-file=/etc/ssl/sstp-ca.crt
|
||||
#ssl-pemfile=/etc/ssl/sstp-cert.pem
|
||||
#ssl-keyfile=/etc/ssl/sstp-key.pem
|
||||
#host-name=domain.tld
|
||||
#http-error=allow
|
||||
#timeout=60
|
||||
#hello-interval=60
|
||||
#ip-pool=sstp
|
||||
#ipv6-pool=sstp
|
||||
#ipv6-pool-delegate=sstp
|
||||
ifname=sstp%d
|
||||
|
||||
[ipoe]
|
||||
verbose=1
|
||||
username=ifname
|
||||
#password=username
|
||||
lease-time=600
|
||||
#renew-time=300
|
||||
#rebind-time=525
|
||||
max-lease-time=3600
|
||||
#unit-cache=1000
|
||||
#l4-redirect-table=4
|
||||
#l4-redirect-ipset=l4
|
||||
#l4-redirect-on-reject=300
|
||||
#l4-redirect-ip-pool=pool1
|
||||
shared=0
|
||||
ifcfg=1
|
||||
mode=L2
|
||||
start=dhcpv4
|
||||
#start=up
|
||||
#ip-unnumbered=1
|
||||
#proxy-arp=0
|
||||
#nat=0
|
||||
#proto=100
|
||||
#relay=10.10.10.10
|
||||
#vendor=Custom
|
||||
#weight=0
|
||||
#attr-dhcp-client-ip=DHCP-Client-IP-Address
|
||||
#attr-dhcp-router-ip=DHCP-Router-IP-Address
|
||||
#attr-dhcp-mask=DHCP-Mask
|
||||
#attr-dhcp-lease-time=DHCP-Lease-Time
|
||||
#attr-dhcp-renew-time=DHCP-Renewal-Time
|
||||
#attr-dhcp-rebind-time=DHCP-Rebinding-Time
|
||||
#attr-dhcp-opt82=DHCP-Option82
|
||||
#attr-dhcp-opt82-remote-id=DHCP-Agent-Remote-Id
|
||||
#attr-dhcp-opt82-circuit-id=DHCP-Agent-Circuit-Id
|
||||
#attr-l4-redirect=L4-Redirect
|
||||
#attr-l4-redirect-table=4
|
||||
#attr-l4-redirect-ipset=l4-redirect
|
||||
#lua-file=/etc/accel-ppp.lua
|
||||
#offer-delay=0,100:100,200:200,-1:1000
|
||||
#vlan-mon=eth0,10-200
|
||||
#vlan-timeout=60
|
||||
#vlan-name=%I.%N
|
||||
#ip-pool=ipoe
|
||||
#ipv6-pool=ipoe
|
||||
#ipv6-pool-delegate=ipoe
|
||||
#idle-timeout=0
|
||||
#session-timeout=0
|
||||
#soft-terminate=0
|
||||
#check-mac-change=1
|
||||
#calling-sid=mac
|
||||
#local-net=192.168.0.0/16
|
||||
interface=eth0
|
||||
|
||||
[dns]
|
||||
#dns1=172.16.0.1
|
||||
#dns2=172.16.1.1
|
||||
|
||||
[wins]
|
||||
#wins1=172.16.0.1
|
||||
#wins2=172.16.1.1
|
||||
|
||||
[radius]
|
||||
#dictionary=/usr/local/share/accel-ppp/radius/dictionary
|
||||
nas-identifier=accel-ppp
|
||||
nas-ip-address=127.0.0.1
|
||||
gw-ip-address=192.168.100.1
|
||||
server=127.0.0.1,testing123,auth-port=1812,acct-port=1813,req-limit=50,fail-timeout=0,max-fail=10,weight=1
|
||||
dae-server=127.0.0.1:3799,testing123
|
||||
verbose=1
|
||||
#timeout=3
|
||||
#max-try=3
|
||||
#acct-timeout=120
|
||||
#acct-delay-time=0
|
||||
#acct-delay-start=0
|
||||
#acct-on=0
|
||||
#acct-interim-interval=0
|
||||
#acct-interim-jitter=0
|
||||
#default-realm=
|
||||
#strip-realm=0
|
||||
#attr-tunnel-type=My-Tunnel-Type
|
||||
#nas-port-id-in-req=1
|
||||
|
||||
[client-ip-range]
|
||||
0.0.0.0/0
|
||||
|
||||
[ip-pool]
|
||||
gw-ip-address=192.168.0.1
|
||||
#vendor=Cisco
|
||||
#attr=Cisco-AVPair
|
||||
attr=Framed-Pool
|
||||
192.168.0.2-255
|
||||
192.168.1.1-255,name=pool1
|
||||
192.168.2.1-255,name=pool2
|
||||
192.168.3.1-255,name=pool3
|
||||
192.168.4.1-255,name=pool4,next=pool1
|
||||
192.168.4.0/24
|
||||
|
||||
[log]
|
||||
log-file=/tmp/accel-ppp.log
|
||||
log-emerg=/tmpaccel-ppp-emerg.log
|
||||
log-fail-file=/tmp/accel-ppp-auth-fail.log
|
||||
#log-debug=/dev/stdout
|
||||
#syslog=accel-pppd,daemon
|
||||
#log-tcp=127.0.0.1:3000
|
||||
copy=1
|
||||
#color=1
|
||||
#per-user-dir=per_user
|
||||
#per-session-dir=per_session
|
||||
#per-session=1
|
||||
level=7
|
||||
|
||||
[log-pgsql]
|
||||
conninfo=user=log
|
||||
log-table=log
|
||||
|
||||
[pppd-compat]
|
||||
verbose=1
|
||||
#ip-pre-up=/etc/ppp/ip-pre-up
|
||||
ip-up=/etc/ppp/ip-up
|
||||
ip-down=/etc/ppp/ip-down
|
||||
#ip-change=/etc/ppp/ip-change
|
||||
radattr-prefix=/var/run/radattr
|
||||
#fork-limit=16
|
||||
|
||||
[chap-secrets]
|
||||
gw-ip-address=192.168.100.1
|
||||
#chap-secrets=/etc/ppp/chap-secrets
|
||||
#encrypted=0
|
||||
#username-hash=md5
|
||||
|
||||
[shaper]
|
||||
#attr=Filter-Id
|
||||
#down-burst-factor=0.1
|
||||
#up-burst-factor=1.0
|
||||
#latency=50
|
||||
#mpu=0
|
||||
#mtu=0
|
||||
#r2q=10
|
||||
#quantum=1500
|
||||
#moderate-quantum=1
|
||||
#cburst=1534
|
||||
#ifb=ifb0
|
||||
up-limiter=police
|
||||
down-limiter=tbf
|
||||
#leaf-qdisc=sfq perturb 10
|
||||
#leaf-qdisc=fq_codel [limit PACKETS] [flows NUMBER] [target TIME] [interval TIME] [quantum BYTES] [[no]ecn]
|
||||
#rate-multiplier=1
|
||||
#fwmark=1
|
||||
#rate-limit=2048/1024
|
||||
verbose=1
|
||||
|
||||
[cli]
|
||||
verbose=1
|
||||
telnet=127.0.0.1:2000
|
||||
tcp=127.0.0.1:2001
|
||||
#password=123
|
||||
#sessions-columns=ifname,username,ip,ip6,ip6-dp,type,state,uptime,uptime-raw,calling-sid,called-sid,sid,comp,inbound-if,service-name,rx-bytes,tx-bytes,rx-bytes-raw,tx-bytes-raw,rx-pkts,tx-pkts,netns,vrf
|
||||
|
||||
[snmp]
|
||||
master=0
|
||||
agent-name=accel-ppp
|
||||
|
||||
[connlimit]
|
||||
limit=10/min
|
||||
burst=3
|
||||
timeout=60
|
||||
|
||||
[ipv6-pool]
|
||||
#gw-ip6-address=fc00:0:1::1
|
||||
#vendor=
|
||||
#attr-prefix=Delegated-IPv6-Prefix-Pool
|
||||
#attr-address=Stateful-IPv6-Address-Pool
|
||||
fc00:0:1::/48,64
|
||||
fc00:0:2::/48,64,name=pool1
|
||||
fc00:0:3::/48,64,name=pool2,next=pool1
|
||||
delegate=fc00:1::/36,48
|
||||
delegate=fc00:2::/36,48,name=pool3
|
||||
delegate=fc00:3::/36,48,name=pool4,next=pool3
|
||||
|
||||
[ipv6-dns]
|
||||
#fc00:1::1
|
||||
#fc00:1::2
|
||||
#fc00:1::3
|
||||
#dnssl=suffix1.local.net
|
||||
#dnssl=suffix2.local.net.
|
||||
|
||||
[ipv6-dhcp]
|
||||
verbose=1
|
||||
pref-lifetime=604800
|
||||
valid-lifetime=2592000
|
||||
route-via-gw=1
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=35
|
||||
STOP=85
|
||||
USE_PROCD=1
|
||||
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param command /usr/sbin/accel-pppd -d -c /etc/accel-ppp/accel-ppp.conf -p /var/run/accel-pppd.pid
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service(){
|
||||
killall -9 accel-pppd >/dev/null 2>&1
|
||||
rm -rf /var/run/accel-pppd.pid
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
procd_send_signal accel-ppp
|
||||
}
|
||||
|
||||
service_triggers()
|
||||
{
|
||||
procd_add_reload_trigger accel-ppp
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
Index: accel-ppp-1.13.0/accel-pppd/ctrl/ipoe/arp.c
|
||||
===================================================================
|
||||
--- accel-ppp-1.13.0.orig/accel-pppd/ctrl/ipoe/arp.c
|
||||
+++ accel-ppp-1.13.0/accel-pppd/ctrl/ipoe/arp.c
|
||||
@@ -14,9 +14,9 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef HAVE_GOOD_IFARP
|
||||
-#include <linux/if_arp.h>
|
||||
+#include <net/if_arp.h>
|
||||
#endif
|
||||
-#include <linux/if_packet.h>
|
||||
+#include <netpacket/packet.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "triton.h"
|
||||
Index: accel-ppp-1.13.0/accel-pppd/ctrl/ipoe/ipoe.c
|
||||
===================================================================
|
||||
--- accel-ppp-1.13.0.orig/accel-pppd/ctrl/ipoe/ipoe.c
|
||||
+++ accel-ppp-1.13.0/accel-pppd/ctrl/ipoe/ipoe.c
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if.h>
|
||||
#ifdef HAVE_GOOD_IFARP
|
||||
-#include <linux/if_arp.h>
|
||||
+#include <net/if_arp.h>
|
||||
#endif
|
||||
#include <linux/route.h>
|
||||
|
||||
Index: accel-ppp-1.13.0/accel-pppd/ctrl/pppoe/pppoe.c
|
||||
===================================================================
|
||||
--- accel-ppp-1.13.0.orig/accel-pppd/ctrl/pppoe/pppoe.c
|
||||
+++ accel-ppp-1.13.0/accel-pppd/ctrl/pppoe/pppoe.c
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
+#include <linux/sockios.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <arpa/inet.h>
|
||||
Index: accel-ppp-1.13.0/accel-pppd/include/ap_session.h
|
||||
===================================================================
|
||||
--- accel-ppp-1.13.0.orig/accel-pppd/include/ap_session.h
|
||||
+++ accel-ppp-1.13.0/accel-pppd/include/ap_session.h
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "triton.h"
|
||||
#include "ap_net.h"
|
||||
+#include "pthread.h"
|
||||
|
||||
//#define AP_SESSIONID_LEN 16
|
||||
#define AP_IFNAME_LEN 16
|
||||
@@ -124,9 +125,9 @@ struct ap_session
|
||||
|
||||
struct ap_session_stat
|
||||
{
|
||||
- unsigned int active;
|
||||
- unsigned int starting;
|
||||
- unsigned int finishing;
|
||||
+ uint32_t active;
|
||||
+ uint32_t starting;
|
||||
+ uint32_t finishing;
|
||||
};
|
||||
|
||||
|
||||
Index: accel-ppp-1.13.0/accel-pppd/ppp/ppp.c
|
||||
===================================================================
|
||||
--- accel-ppp-1.13.0.orig/accel-pppd/ppp/ppp.c
|
||||
+++ accel-ppp-1.13.0/accel-pppd/ppp/ppp.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
+#include <linux/sockios.h>
|
||||
#include "linux_ppp.h"
|
||||
|
||||
#include "crypto.h"
|
||||
Index: accel-ppp-1.13.0/accel-pppd/session_backup.c
|
||||
===================================================================
|
||||
--- accel-ppp-1.13.0.orig/accel-pppd/session_backup.c
|
||||
+++ accel-ppp-1.13.0/accel-pppd/session_backup.c
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
-
|
||||
+#include "pthread.h"
|
||||
#include "events.h"
|
||||
#include "triton.h"
|
||||
#include "log.h"
|
||||
@@ -1,85 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (c) 2023-2025 AnYun
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=aic8800
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_DATE:=2025-07-02
|
||||
PKG_SOURCE_URL:=https://github.com/radxa-pkg/aic8800.git
|
||||
PKG_SOURCE_VERSION:=85821b562b5c45cfb6a6195a86c96e978638d50f
|
||||
PKG_MIRROR_HASH:=skip
|
||||
|
||||
ifeq ($(BUILD_VARIANT),sdio)
|
||||
MAKE_PATH:=src/SDIO/driver_fw/driver/aic8800
|
||||
PATCH_DIR:=$(CURDIR)/patches-sdio
|
||||
else
|
||||
MAKE_PATH:=src/USB/driver_fw/drivers/aic8800
|
||||
PATCH_DIR:=$(CURDIR)/patches-usb
|
||||
endif
|
||||
|
||||
PKG_EXTMOD_SUBDIRS:=$(MAKE_PATH)
|
||||
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/aic8800s
|
||||
SUBMENU:=Wireless Drivers
|
||||
TITLE:=AIC8800 SDIO wireless support
|
||||
DEPENDS:=+kmod-mac80211 +kmod-mmc \
|
||||
+@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT
|
||||
FILES:= \
|
||||
$(PKG_BUILD_DIR)/$(MAKE_PATH)/aic8800_bsp/aic8800_bsp.ko \
|
||||
$(PKG_BUILD_DIR)/$(MAKE_PATH)/aic8800_fdrv/aic8800_fdrv.ko
|
||||
AUTOLOAD:=$(call AutoProbe,aic8800_bsp aic8800_fdrv)
|
||||
VARIANT:=sdio
|
||||
endef
|
||||
|
||||
define KernelPackage/aic8800u
|
||||
SUBMENU:=Wireless Drivers
|
||||
TITLE:=AIC8800 USB wireless support
|
||||
DEPENDS:=+kmod-mac80211 +kmod-usb-core @USB_SUPPORT \
|
||||
+@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT
|
||||
FILES:= \
|
||||
$(PKG_BUILD_DIR)/$(MAKE_PATH)/aic_load_fw/aic_load_fw.ko \
|
||||
$(PKG_BUILD_DIR)/$(MAKE_PATH)/aic8800_fdrv/aic8800_usb.ko
|
||||
AUTOLOAD:=$(call AutoProbe,aic_load_fw aic8800_usb)
|
||||
VARIANT:=usb
|
||||
endef
|
||||
|
||||
NOSTDINC_FLAGS := \
|
||||
$(KERNEL_NOSTDINC_FLAGS) \
|
||||
-I$(PKG_BUILD_DIR) \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211-backport \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211/uapi \
|
||||
-I$(STAGING_DIR)/usr/include/mac80211 \
|
||||
-include backport/backport.h
|
||||
|
||||
EXTRA_CFLAGS:= -DBUILD_OPENWRT
|
||||
|
||||
define Build/Compile
|
||||
+$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \
|
||||
NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \
|
||||
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
|
||||
$(KERNEL_MAKE_FLAGS) \
|
||||
M="$(PKG_BUILD_DIR)/$(MAKE_PATH)/" \
|
||||
modules
|
||||
endef
|
||||
|
||||
define KernelPackage/aic8800s/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/aic8800
|
||||
$(CP) $(PKG_BUILD_DIR)/src/SDIO/driver_fw/fw/aic8800D80/* $(1)/lib/firmware/aic8800
|
||||
endef
|
||||
|
||||
define KernelPackage/aic8800u/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware
|
||||
$(CP) $(PKG_BUILD_DIR)/src/USB/driver_fw/fw/* $(1)/lib/firmware
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,aic8800s))
|
||||
$(eval $(call KernelPackage,aic8800u))
|
||||
@@ -1,95 +0,0 @@
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
@@ -1579,7 +1579,7 @@ static struct rwnx_vif *rwnx_interface_a
|
||||
vif->ap.generation = 0;
|
||||
vif->ap.mesh_pm = NL80211_MESH_POWER_ACTIVE;
|
||||
vif->ap.next_mesh_pm = NL80211_MESH_POWER_ACTIVE;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
INIT_LIST_HEAD(&vif->ap.sta_list);
|
||||
memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn));
|
||||
@@ -1996,7 +1996,7 @@ static int rwnx_cfg80211_change_iface(st
|
||||
INIT_LIST_HEAD(&vif->ap.proxy_list);
|
||||
vif->ap.create_path = false;
|
||||
vif->ap.generation = 0;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
INIT_LIST_HEAD(&vif->ap.sta_list);
|
||||
@@ -3952,6 +3952,7 @@ static int rwnx_cfg80211_mgmt_tx(struct
|
||||
switch (RWNX_VIF_TYPE(rwnx_vif)) {
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
rwnx_vif = rwnx_vif->ap_vlan.master;
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
@@ -4261,7 +4262,7 @@ rwnx_cfg80211_tdls_mgmt(struct wiphy *wi
|
||||
printk("%s: only one TDLS link is supported!\n", __func__);
|
||||
status_code = WLAN_STATUS_REQUEST_DECLINED;
|
||||
}
|
||||
- /* fall-through */
|
||||
+ fallthrough;
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
@@ -4594,6 +4595,7 @@ static int rwnx_fill_station_info(struct
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
|
||||
case FORMATMOD_HE_MU:
|
||||
sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size;
|
||||
+ fallthrough;
|
||||
case FORMATMOD_HE_SU:
|
||||
case FORMATMOD_HE_ER:
|
||||
sinfo->rxrate.flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_msg_tx.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_msg_tx.c
|
||||
@@ -524,7 +524,7 @@ int rwnx_send_add_if (struct rwnx_hw *rw
|
||||
//case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
add_if_req_param->p2p = true;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
case NL80211_IFTYPE_STATION:
|
||||
add_if_req_param->type = MM_STA;
|
||||
@@ -537,7 +537,7 @@ int rwnx_send_add_if (struct rwnx_hw *rw
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
add_if_req_param->p2p = true;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
case NL80211_IFTYPE_AP:
|
||||
add_if_req_param->type = MM_AP;
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_tdls.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_tdls.c
|
||||
@@ -257,6 +257,7 @@ static u8 rwnx_ac_from_wmm(int ac)
|
||||
switch (ac) {
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
+ fallthrough;
|
||||
case 0:
|
||||
return AC_BE;
|
||||
case 1:
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_tx.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_tx.c
|
||||
@@ -332,6 +332,7 @@ u16 rwnx_select_txq(struct rwnx_vif *rwn
|
||||
/* AP_VLAN interface is not used for a 4A STA,
|
||||
fallback searching sta amongs all AP's clients */
|
||||
rwnx_vif = rwnx_vif->ap_vlan.master;
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
{
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_txq.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_txq.c
|
||||
@@ -640,6 +640,7 @@ static inline void rwnx_txq_vif_for_each
|
||||
}
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
rwnx_vif = rwnx_vif->ap_vlan.master;
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
@@ -1,12 +0,0 @@
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_bsp/Makefile
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_bsp/Makefile
|
||||
@@ -1,7 +1,7 @@
|
||||
CONFIG_SDIO_SUPPORT := y
|
||||
CONFIG_SDIO_PWRCTRL := y
|
||||
-CONFIG_AIC_FW_PATH = "/vendor/etc/firmware"
|
||||
-#CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800"
|
||||
+#CONFIG_AIC_FW_PATH = "/vendor/etc/firmware"
|
||||
+CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800"
|
||||
export CONFIG_AIC_FW_PATH
|
||||
ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\"
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
@@ -785,7 +785,7 @@ static void rwnx_csa_finish(struct work_
|
||||
} else
|
||||
rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw);
|
||||
spin_unlock_bh(&rwnx_hw->cb_lock);
|
||||
-#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3)
|
||||
+#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3) || defined(BUILD_OPENWRT)
|
||||
cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0, 0);
|
||||
#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION)
|
||||
cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0);
|
||||
@@ -4177,7 +4177,7 @@ int rwnx_cfg80211_channel_switch (struct
|
||||
goto end;
|
||||
} else {
|
||||
INIT_WORK(&csa->work, rwnx_csa_finish);
|
||||
-#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4
|
||||
+#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4 || defined(BUILD_OPENWRT)
|
||||
cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false, 0);
|
||||
#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2
|
||||
cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false);
|
||||
@@ -4206,6 +4206,9 @@ rwnx_cfg80211_tdls_mgmt(struct wiphy *wi
|
||||
#else
|
||||
u8 *peer,
|
||||
#endif
|
||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0) || defined(BUILD_OPENWRT)
|
||||
+ int link_id,
|
||||
+#endif
|
||||
u8 action_code,
|
||||
u8 dialog_token,
|
||||
u16 status_code,
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_mod_params.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_mod_params.c
|
||||
@@ -1763,7 +1763,9 @@ void rwnx_custregd(struct rwnx_hw *rwnx_
|
||||
if (!rwnx_hw->mod_params->custregd)
|
||||
return;
|
||||
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) && !defined(BUILD_OPENWRT)
|
||||
wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
|
||||
+#endif
|
||||
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
|
||||
|
||||
rtnl_lock();
|
||||
@@ -1,33 +0,0 @@
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_bsp/aic_bsp_main.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_bsp/aic_bsp_main.c
|
||||
@@ -15,7 +15,7 @@
|
||||
#define DRV_AUTHOR "AICSemi"
|
||||
#define DRV_VERS_MOD "1.0"
|
||||
|
||||
-int aicwf_dbg_level_bsp = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE;
|
||||
+int aicwf_dbg_level_bsp = LOGDATA;
|
||||
|
||||
struct semaphore aicbsp_probe_semaphore;
|
||||
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
@@ -510,7 +510,7 @@ static const int rwnx_hwq2uapsd[NL80211_
|
||||
|
||||
|
||||
extern uint8_t scanning;
|
||||
-int aicwf_dbg_level = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE;
|
||||
+int aicwf_dbg_level = LOGWAKELOCK;
|
||||
module_param(aicwf_dbg_level, int, 0660);
|
||||
int testmode = 0;
|
||||
char aic_fw_path[200];
|
||||
--- a/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_platform.c
|
||||
+++ b/src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/rwnx_platform.c
|
||||
@@ -792,7 +792,7 @@ s8_l get_txpwr_max(s8_l power)
|
||||
}
|
||||
}
|
||||
|
||||
- printk("%s:txpwr_max:%d \r\n",__func__,power);
|
||||
+ //printk("%s:txpwr_max:%d \r\n",__func__,power);
|
||||
return power;
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
@@ -1854,7 +1854,7 @@ static struct rwnx_vif *rwnx_interface_a
|
||||
vif->ap.generation = 0;
|
||||
vif->ap.mesh_pm = NL80211_MESH_POWER_ACTIVE;
|
||||
vif->ap.next_mesh_pm = NL80211_MESH_POWER_ACTIVE;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
INIT_LIST_HEAD(&vif->ap.sta_list);
|
||||
memset(&vif->ap.bcn, 0, sizeof(vif->ap.bcn));
|
||||
@@ -2309,7 +2309,7 @@ static int rwnx_cfg80211_change_iface(st
|
||||
INIT_LIST_HEAD(&vif->ap.proxy_list);
|
||||
vif->ap.create_path = false;
|
||||
vif->ap.generation = 0;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
INIT_LIST_HEAD(&vif->ap.sta_list);
|
||||
@@ -4459,6 +4459,7 @@ static int rwnx_cfg80211_mgmt_tx(struct
|
||||
switch (RWNX_VIF_TYPE(rwnx_vif)) {
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
rwnx_vif = rwnx_vif->ap_vlan.master;
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
@@ -5132,6 +5133,7 @@ static int rwnx_fill_station_info(struct
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
|
||||
case FORMATMOD_HE_MU:
|
||||
sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size;
|
||||
+ fallthrough;
|
||||
case FORMATMOD_HE_SU:
|
||||
case FORMATMOD_HE_ER:
|
||||
sinfo->rxrate.flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_mod_params.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_mod_params.c
|
||||
@@ -936,7 +936,7 @@ static void rwnx_set_vht_capa(struct rwn
|
||||
if(rwnx_hw->usbdev->chipid <= PRODUCT_ID_AIC8800D81)
|
||||
nss = 1;
|
||||
|
||||
- band_2GHz->vht_cap.vht_supported = true;
|
||||
+ band_2GHz->vht_cap.vht_supported = true;
|
||||
if (rwnx_hw->mod_params->sgi80)
|
||||
band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
|
||||
if (rwnx_hw->mod_params->stbc_on)
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_msg_tx.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_msg_tx.c
|
||||
@@ -613,7 +613,7 @@ int rwnx_send_add_if(struct rwnx_hw *rwn
|
||||
//case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
add_if_req_param->p2p = true;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
case NL80211_IFTYPE_STATION:
|
||||
add_if_req_param->type = MM_STA;
|
||||
@@ -626,7 +626,7 @@ int rwnx_send_add_if(struct rwnx_hw *rwn
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
add_if_req_param->p2p = true;
|
||||
- // no break
|
||||
+ fallthrough;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
case NL80211_IFTYPE_AP:
|
||||
add_if_req_param->type = MM_AP;
|
||||
@@ -1443,6 +1443,7 @@ int rwnx_send_vendor_hwconfig_req(struct
|
||||
printk("get_chip_temp err=%d\n", error);
|
||||
}
|
||||
}
|
||||
+ break;
|
||||
case CUSTOMIZED_FREQ_REQ:
|
||||
/* Build the CUSTOMIZED_FREQ_REQ message */
|
||||
req5 = rwnx_msg_zalloc(MM_SET_VENDOR_HWCONFIG_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_customized_freq_req));
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_tdls.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_tdls.c
|
||||
@@ -263,6 +263,7 @@ static u8 rwnx_ac_from_wmm(int ac)
|
||||
switch (ac) {
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
+ fallthrough;
|
||||
case 0:
|
||||
return AC_BE;
|
||||
case 1:
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_tx.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_tx.c
|
||||
@@ -328,6 +328,7 @@ u16 rwnx_select_txq(struct rwnx_vif *rwn
|
||||
/* AP_VLAN interface is not used for a 4A STA,
|
||||
fallback searching sta amongs all AP's clients */
|
||||
rwnx_vif = rwnx_vif->ap_vlan.master;
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
{
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_txq.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_txq.c
|
||||
@@ -638,6 +638,7 @@ void rwnx_txq_vif_for_each_sta(struct rw
|
||||
}
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
rwnx_vif = rwnx_vif->ap_vlan.master;
|
||||
+ fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
@@ -1,50 +0,0 @@
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
@@ -1073,7 +1073,7 @@ static void rwnx_csa_finish(struct work_
|
||||
} else
|
||||
rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw);
|
||||
spin_unlock_bh(&rwnx_hw->cb_lock);
|
||||
-#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3)
|
||||
+#if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3) || defined(BUILD_OPENWRT)
|
||||
cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0, 0);
|
||||
#elif (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION)
|
||||
cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0);
|
||||
@@ -3727,7 +3727,7 @@ static int rwnx_cfg80211_start_ap(struct
|
||||
* @change_beacon: Change the beacon parameters for an access point mode
|
||||
* interface. This should reject the call when AP mode wasn't started.
|
||||
*/
|
||||
-#if LINUX_VERSION_CODE > KERNEL_VERSION(6, 7, 0)
|
||||
+#if LINUX_VERSION_CODE > KERNEL_VERSION(6, 7, 0) && !defined(BUILD_OPENWRT)
|
||||
static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_ap_update *info)
|
||||
#else
|
||||
@@ -3747,7 +3747,7 @@ static int rwnx_cfg80211_change_beacon(s
|
||||
elem.dma_addr = 0;
|
||||
|
||||
// Build the beacon
|
||||
-#if LINUX_VERSION_CODE > KERNEL_VERSION(6, 7, 0)
|
||||
+#if LINUX_VERSION_CODE > KERNEL_VERSION(6, 7, 0) && !defined(BUILD_OPENWRT)
|
||||
buf = rwnx_build_bcn(bcn, &info->beacon);
|
||||
#else
|
||||
buf = rwnx_build_bcn(bcn, info);
|
||||
@@ -4709,7 +4709,7 @@ int rwnx_cfg80211_channel_switch(struct
|
||||
goto end;
|
||||
} else {
|
||||
INIT_WORK(&csa->work, rwnx_csa_finish);
|
||||
-#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4
|
||||
+#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4 || defined(BUILD_OPENWRT)
|
||||
cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false, 0);
|
||||
#elif LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION2
|
||||
cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false);
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_mod_params.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_mod_params.c
|
||||
@@ -1833,7 +1833,9 @@ void rwnx_custregd(struct rwnx_hw *rwnx_
|
||||
// registration (in rwnx_set_wiphy_params()), so nothing has to be done here
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) && !defined(BUILD_OPENWRT)
|
||||
wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
|
||||
+#endif
|
||||
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
|
||||
|
||||
if (!rwnx_hw->mod_params->custregd)
|
||||
@@ -1,22 +0,0 @@
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/rwnx_main.c
|
||||
@@ -525,7 +525,7 @@ static const int rwnx_hwq2uapsd[NL80211_
|
||||
struct semaphore aicwf_deinit_sem;
|
||||
atomic_t aicwf_deinit_atomic;
|
||||
|
||||
-int aicwf_dbg_level = LOGERROR|LOGINFO;
|
||||
+int aicwf_dbg_level = LOGDATA;
|
||||
module_param(aicwf_dbg_level, int, 0660);
|
||||
|
||||
int testmode = 0;
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic_load_fw/aic_bluetooth_main.c
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic_load_fw/aic_bluetooth_main.c
|
||||
@@ -20,7 +20,7 @@ int adap_test = 0;
|
||||
char paringid[100];
|
||||
int n_para = 1;
|
||||
int ble_scan_wakeup_reboot_time = 1000;
|
||||
-int aicwf_dbg_level = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE;
|
||||
+int aicwf_dbg_level = LOGDATA;
|
||||
int flash_erase_len = 0x400000;
|
||||
uint32_t ad_data_filter_mask = 0;
|
||||
uint32_t gpio_num = 2;//default select gpiob2 for fw_wakeup_host
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/Makefile
|
||||
+++ b/src/USB/driver_fw/drivers/aic8800/aic8800_fdrv/Makefile
|
||||
@@ -5,7 +5,7 @@ EXTRA_CFLAGS += -Wno-implicit-fallthroug
|
||||
RWNX_VERS_NUM := 6.4.3.0
|
||||
|
||||
CONFIG_AIC8800_WLAN_SUPPORT = m
|
||||
-MODULE_NAME = aic8800_fdrv
|
||||
+MODULE_NAME = aic8800_usb
|
||||
CONFIG_COUNTRY_CODE = "00"
|
||||
|
||||
# Support of bootrom start
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 75 KiB |
@@ -1,89 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="270.933mm" height="270.933mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 27093.32 27093.32"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.str4 {stroke:#121631;stroke-width:449.79;stroke-miterlimit:22.9256}
|
||||
.str6 {stroke:#374244;stroke-width:238.12;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:22.9256}
|
||||
.str5 {stroke:#4781B3;stroke-width:317.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:22.9256}
|
||||
.str2 {stroke:#121631;stroke-width:264.58;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:22.9256}
|
||||
.str7 {stroke:#FCFCFC;stroke-width:132.29;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:22.9256}
|
||||
.str0 {stroke:#121631;stroke-width:449.79;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:22.9256}
|
||||
.str3 {stroke:#764C3E;stroke-width:264.58;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:22.9256}
|
||||
.str1 {stroke:#255D96;stroke-width:264.58;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:22.9256;stroke-dasharray:529.160000 529.160000}
|
||||
.fil2 {fill:none}
|
||||
.fil4 {fill:#121631}
|
||||
.fil1 {fill:#255D96}
|
||||
.fil0 {fill:#4781B3}
|
||||
.fil11 {fill:#6F7478}
|
||||
.fil10 {fill:#878F92}
|
||||
.fil9 {fill:#898E92}
|
||||
.fil7 {fill:#A6ABAF}
|
||||
.fil8 {fill:#D2D6DF}
|
||||
.fil5 {fill:#EBAE99}
|
||||
.fil3 {fill:#FBFBFB}
|
||||
.fil6 {fill:#FCFBFB}
|
||||
.fil12 {fill:#FCFCFC}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="finR">
|
||||
<path id="body" class="fil0" d="M12688.37 11247.31c0,0 -835.46,815.77 -1491.41,1140.69 -655.94,324.92 -1153.61,555.28 -1806.24,790.52 -652.63,235.23 -746.27,856.99 28.89,1241.38 775.16,384.39 1778.21,634.6 2887.59,468.58 1109.39,-166.03 1219.93,-288.57 1219.93,-288.57l-838.76 -3352.6z"/>
|
||||
<path id="shadow" class="fil1" d="M12688.37 11247.31c0,0 -835.46,815.77 -1491.41,1140.69 -655.94,324.92 -1153.61,555.28 -1806.24,790.52 -652.63,235.23 -746.27,856.99 28.89,1241.38 775.16,384.39 1778.21,634.6 2887.59,468.58 1109.39,-166.03 1219.93,-288.57 1219.93,-288.57l-838.76 -3352.6z"/>
|
||||
<path id="edge" class="fil2 str0" d="M12688.37 11247.31c0,0 -835.46,815.77 -1491.41,1140.69 -655.94,324.92 -1153.61,555.28 -1806.24,790.52 -652.63,235.23 -746.27,856.99 28.89,1241.38 775.16,384.39 1778.21,634.6 2887.59,468.58 1109.39,-166.03 1219.93,-288.57 1219.93,-288.57"/>
|
||||
</g>
|
||||
<g id="shark">
|
||||
<g id="body_10">
|
||||
<path id="finT" class="fil1" d="M20987.55 16728.79c677.2,191.39 754.78,114.96 1459.46,815.38 290.01,288.27 374.55,642.49 779.88,558.59 338.07,-69.98 378.2,-504.49 355.7,-1104.44 -22.5,-599.95 -206.83,-1671.62 -534.74,-2561.64 -327.91,-890.02 -1428.17,-2551.94 -1482.18,-2138.02l-578.12 4430.13z"/>
|
||||
<path id="base" class="fil0" d="M9021.05 19010.83c-713.87,-713.89 -2018.96,-1818.68 -2816.58,-2047.03 -797.62,-228.35 -1970.08,-427.28 -2189.4,-89.88 -219.32,337.4 244.86,1169.8 1217.13,1817.57 972.27,647.77 1744.34,939 2000.54,1057.73 256.2,118.73 -702.89,814.24 -1028.27,1807.86 -325.38,993.62 -403.22,2047.35 286.83,2421.48 690.05,374.13 1499.18,-318.66 2061.85,-1158.01 562.67,-839.35 650.27,-1790.46 757.16,-1772.65 106.89,17.81 2001.38,516.65 3426.64,543.37 1425.26,26.72 3388.6,-13.24 4933.09,-607.48 1544.49,-594.24 3028.3,-2181.12 3619.59,-3632.45 591.29,-1451.33 852.47,-2889.99 832.22,-5046.14 -20.25,-2156.15 -499.33,-4772.61 -1101.63,-6232.11 -602.3,-1459.5 -2343.48,-4008.18 -4298.98,-3927.81 -1955.5,80.37 -4024.75,3152.8 -4661.05,5461.64 -700.59,2542.13 -451.63,4682.16 23.63,6956.09 542.67,2596.48 -3062.77,4447.82 -3062.77,4447.82z"/>
|
||||
<path id="shadow_11" class="fil1" d="M18132.32 18397.36c0,0 -586.43,664.34 -1202.54,1054.34 -616.11,390 -205.46,56.83 0,187.85 205.46,131.02 467.48,358.1 -12.9,672.54 -480.38,314.44 -2335.66,1081.73 -5308.32,963.47 -3105.11,-123.54 -4550.11,-3828.53 -4710.76,-4463.4l11234.52 1585.2z"/>
|
||||
<path id="curve" class="fil2 str1" d="M18600.82 2782.34c-290.31,-100.71 -589.3,-151.83 -893.46,-139.33 -1091.85,44.87 -2219.16,1022.55 -3112.7,2279.23"/>
|
||||
<path id="belly" class="fil3" d="M14631.87 3709.62c1424.07,171.04 2205.72,2770.01 2211.93,7990.58 5.58,4693.84 -1438.46,5611.51 -2607.69,5624.1 -1301,14.01 -2563.14,-2426.48 -2610.73,-6469.05 -47.42,-4028.08 2111.03,-7253.18 3006.49,-7145.63z"/>
|
||||
<path id="gill" class="fil2 str2" d="M17154.83 11229.59c0,0 1080.45,181.15 1850.35,-58.23m-1751.88 906.92c0,0 850.81,195.69 1803.71,38.29m-1833.39 770.55c0,0 788.49,267.07 1781.56,48.89"/>
|
||||
</g>
|
||||
<g id="eye">
|
||||
<ellipse id="eye_12" class="fil4" cx="17282.57" cy="8294.69" rx="419.35" ry="525.42"/>
|
||||
<ellipse id="eye_13" class="fil3" cx="17285" cy="8015.89" rx="212.7" ry="266.5"/>
|
||||
</g>
|
||||
<g id="mouth">
|
||||
<path id="body_14" class="fil5" d="M12793.28 5822.58c275.86,129.84 830.32,419.19 1173.24,789.58 470.78,508.5 1184.76,1436.99 1522.86,2497.96 338.1,1060.98 201.99,1866.66 -573.61,880.76 -775.6,-985.91 -1749.61,-1913.39 -2869.25,-2171.8 127.89,-688.86 381.73,-1353.41 746.76,-1996.5z"/>
|
||||
<path id="teeth" class="fil6 str3" d="M12775.03 5804.33c560.33,252.55 894.8,369.92 1848.79,1622.8 953.99,1252.88 904.31,1966.6 904.31,1966.6l-119.63 134.31c0,0 -465.1,-49.73 -581.52,-373.83 -126.3,-351.6 169.22,-644.05 169.22,-644.05 0,0 -487.58,41.68 -677.57,-263.39 -189.99,-305.07 128.49,-773.1 128.49,-773.1 0,0 -476.72,233.83 -741.3,-50.23 -264.58,-284.06 40.48,-806.59 40.48,-806.59 0,0 -361.96,397.16 -727.55,240.48 -365.59,-156.68 -265.53,-796.97 -265.53,-796.97l21.81 -256.03z"/>
|
||||
<path id="edge_15" class="fil2 str4" d="M12626.28 5747.92c0,0 869.45,355.73 1340.24,864.24 470.78,508.5 1184.76,1436.99 1522.86,2497.96 338.1,1060.98 201.99,1866.66 -573.61,880.76 -775.6,-985.91 -1749.61,-1913.39 -2869.25,-2171.8"/>
|
||||
</g>
|
||||
<g id="edge_16">
|
||||
<path id="finT_17" class="fil2 str4" d="M21459.46 16854.39c304.67,87.75 489.48,194.71 987.55,689.78 290.01,288.26 374.55,642.49 779.88,558.59 338.07,-69.98 378.2,-504.49 355.7,-1104.44 -22.5,-599.95 -206.83,-1671.62 -534.74,-2561.64 -175.23,-475.61 -571.01,-1171.65 -909.83,-1653.54"/>
|
||||
<path id="curve_18" class="fil2 str5" d="M12010.73 7609.34c-329.67,1196.21 -449.08,2303.41 -433.6,3377.4m389.11 -1641.59l-684.74 287.65m733.92 -937.6l-684.74 196.13"/>
|
||||
<path id="top" class="fil2 str0" d="M22067.62 14013.65c98.33,-513.62 60.08,-1084.84 54.23,-1708.45 -20.25,-2156.14 -499.33,-4772.61 -1101.63,-6232.11 -602.3,-1459.5 -2343.48,-4008.18 -4298.98,-3927.81 -1955.5,80.37 -4024.75,3152.8 -4661.05,5461.64 -41.73,151.41 -80.09,301.41 -115.23,450.07m-302.63 2097.94c-80.39,1510.77 132.82,2931.19 441.49,4408.08 542.67,2596.47 -3062.77,4447.82 -3062.77,4447.82m0 0c-713.87,-713.89 -1992.87,-1818.68 -2816.58,-2047.03 -823.71,-228.35 -1970.08,-427.28 -2189.4,-89.88 -219.32,337.4 244.86,1169.8 1217.13,1817.57 972.27,647.77 1744.34,939 2000.54,1057.73 256.2,118.73 -702.89,814.24 -1028.27,1807.86 -325.38,993.62 -403.22,2047.35 286.83,2421.48 690.05,374.13 1499.18,-318.66 2061.85,-1158.01 562.67,-839.35 650.27,-1790.46 757.16,-1772.65 106.89,17.81 2001.38,516.65 3426.64,543.37 1425.26,26.72 3388.6,-13.24 4933.09,-607.48 1544.49,-594.24 3028.31,-2181.12 3619.59,-3632.45 108.64,-266.66 227.33,-539.22 280.71,-818.04"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Laptop">
|
||||
<g id="surfaceC">
|
||||
<path id="body_19" class="fil7" d="M10489.67 20461.09c448.74,445.37 1218.14,295.46 1615.01,269.01 396.87,-26.45 4028.3,-707.75 4504.55,-787.12 476.25,-79.37 497.03,-415.22 238.12,-687.92l-4318.48 -4548.45c-142.46,-150.06 -297.78,-166.33 -445.05,-143.6l-4873.93 752.65 3279.78 5145.43z"/>
|
||||
<polygon id="sideL" class="fil8" points="10323.34,20461.09 10899.25,20702.55 11643.68,20775.56 13641.11,20479.3 16771.39,19900.06 17012.21,19583.76 16847.35,19319.64 12774.74,20039.68 11598.43,20181.79 10975.8,20135.33 10531.27,20095.2 "/>
|
||||
<path id="sideLT" class="fil2 str6" d="M10486.88 19871.39c448.74,445.37 1218.14,295.46 1615.01,269.01 333,-22.19 2943.17,-505.41 4056.05,-707.26"/>
|
||||
<path id="edge_20" class="fil2 str0" d="M10489.67 20461.09c448.74,445.37 1218.14,295.46 1615.01,269.01 396.87,-26.45 4028.3,-707.75 4504.55,-787.12 476.25,-79.37 497.03,-415.22 238.12,-687.92l-4318.48 -4548.45c-142.46,-150.06 -297.78,-166.33 -445.05,-143.6l-4873.93 752.65 3279.78 5145.43z"/>
|
||||
</g>
|
||||
<g id="input">
|
||||
<path id="touchpad" class="fil9" d="M12375.18 16350.78l736.05 783.87c47.12,50.17 117.94,64.06 211.21,50.22l745.18 -110.55c84.65,-12.56 127.88,-80.76 66.7,-144.96l-745.03 -781.63c-49.02,-51.44 -77.62,-63.71 -217.47,-39.05l-740.94 130.68c-69.41,12.23 -102.61,61.47 -55.7,111.42z"/>
|
||||
<path id="keyboard" class="fil10" d="M11089.75 15325.47l3182.9 3501.93c105.73,116.32 96.67,325.45 -147.46,365.07l-2377.95 386.03c-282.3,45.82 -521.73,52.8 -715.51,-159l-3030.01 -3311.48 3088.03 -782.55z"/>
|
||||
<path id="button" class="fil11" d="M9293.37 16921.87l137.15 -51.82c65.68,-24.82 171.7,12.24 223.27,73.29l1947.21 2305.59c51.58,61.06 45.42,126.01 -23.64,138.21l-137.15 24.24c-100.17,17.7 -171.34,-12.53 -223.27,-73.29l-1947.22 -2278.02c-51.93,-60.76 -42.03,-113.38 23.65,-138.2zm584.36 -106.51l320.12 -84.16c67.91,-17.85 171.69,12.23 223.27,73.29l1947.21 2305.59c51.59,61.07 45.44,126.01 -23.64,138.21l-320.12 56.58c-100.19,17.71 -171.33,-12.52 -223.27,-73.29l-1947.22 -2278.02c-51.94,-60.77 -44.25,-120.35 23.65,-138.2zm745.41 -131.54l320.12 -84.16c67.91,-17.85 171.69,12.23 223.27,73.29l1947.21 2305.59c51.59,61.07 45.44,126.01 -23.64,138.21l-320.12 56.58c-100.19,17.71 -171.33,-12.52 -223.27,-73.29l-1947.22 -2278.02c-51.94,-60.77 -44.25,-120.35 23.65,-138.2zm695.66 -207.36l373 -76.53c68.78,-14.11 170.17,13.52 223.27,73.29l1149.11 1293.72c53.11,59.78 45.48,126.08 -23.64,138.21l-384.04 67.43c-69.13,12.13 -170.25,-13.43 -223.27,-73.29l-1138.08 -1284.63c-53.02,-59.85 -45.12,-124.09 23.65,-138.2zm-547.96 -564.54l357.48 -93.99c67.91,-17.85 168.48,15.05 223.27,73.29l270.9 288.03c54.79,58.25 45.13,124.11 -23.64,138.21l-373 76.52c-68.76,14.1 -168.38,-15.13 -223.27,-73.29l-255.39 -270.57c-54.89,-58.16 -44.25,-120.35 23.65,-138.2z"/>
|
||||
</g>
|
||||
<path id="surfaceA" class="fil8 str0" d="M6566.49 10205.43l4284.65 4135.13c158.36,140.32 158.36,257.64 158.36,456.49l-479.12 5307.98c-83.19,400.39 -297.44,472.46 -604.5,168.5 -573.54,-567.75 -1089.02,-1235.53 -1620.46,-1836.76 -652.3,-737.97 -1268.62,-1509.45 -1956.95,-2213.95 -53.19,-54.44 -89.2,-91.65 -111.9,-145.61 -22.7,-53.95 -32.1,-124.67 -32.1,-246.15l163.86 -5513.29c-17.15,-172.24 43.81,-217.94 198.16,-112.34z"/>
|
||||
<g id="logos">
|
||||
<polygon id="lightning" class="fil12 str7" points="9311.48,14410.88 7818.85,15097.2 8375.99,15472 7636.07,16232.14 9212.94,15577.28 8639.54,15191.56 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="finL">
|
||||
<path id="body_21" class="fil0" d="M17150.1 14476.2c0,0 -978.37,954.12 -1746.51,1334.14 -768.14,380.02 -1350.93,649.45 -2115.19,924.58 -764.26,275.13 -873.92,1002.33 33.83,1451.91 907.75,449.58 2082.36,742.22 3381.5,548.04 1299.14,-194.18 1428.59,-337.51 1428.59,-337.51l-982.22 -3921.16z"/>
|
||||
<path class="fil2 str1" d="M12682.54 17483.79c0,0 1722.26,351.45 3335.09,-131.54 1612.83,-482.99 2369.96,-1398.38 2369.96,-1398.38"/>
|
||||
<path id="edge_22" class="fil2 str0" d="M17150.1 14476.2c0,0 -978.37,954.12 -1746.51,1334.14 -768.14,380.02 -1350.93,649.45 -2115.19,924.58 -764.26,275.13 -873.92,1002.33 33.83,1451.91 907.75,449.58 2082.36,742.22 3381.5,548.04 1299.14,-194.18 1428.59,-337.51 1428.59,-337.51"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,57 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2010-2011 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=autosamba
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=1
|
||||
PKG_ARCH:=all
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA3 \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA4 \
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/autosamba
|
||||
TITLE:=Samba autoconfig hotplug script.
|
||||
MAINTAINER:=Lean
|
||||
DEPENDS:=+wsdd2 +PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD:luci-app-ksmbd +PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA3:luci-app-samba +PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA4:luci-app-samba4
|
||||
endef
|
||||
|
||||
define Package/autosamba/description
|
||||
A hotplug script to config Samba share automatically.
|
||||
endef
|
||||
|
||||
define Package/$(PKG_NAME)/config
|
||||
choice
|
||||
prompt "Samba Server Selection"
|
||||
default PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_KSMBD
|
||||
bool "KSMBD"
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA3
|
||||
bool "SAMBA 3"
|
||||
|
||||
config PACKAGE_$(PKG_NAME)_INCLUDE_SAMBA4
|
||||
bool "SAMBA 4"
|
||||
endchoice
|
||||
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/autosamba/install
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/block
|
||||
$(INSTALL_BIN) ./files/20-smb $(1)/etc/hotplug.d/block/20-smb
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,autosamba))
|
||||
@@ -1,106 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# D-Team Technology Co.,Ltd. ShenZhen
|
||||
# 作者:Vic
|
||||
#
|
||||
# 警告:对着屏幕的哥们,我们允许你使用此脚本,但不允许你抹去作者的信息,请保留这段话。
|
||||
#
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/service.sh
|
||||
|
||||
global=0
|
||||
config_file="/etc/config/samba4"
|
||||
|
||||
wait_for_init() {
|
||||
for i in `seq 30`
|
||||
do
|
||||
[ -e /tmp/procd.done ] || {
|
||||
sleep 1; continue;
|
||||
}
|
||||
return
|
||||
done
|
||||
}
|
||||
|
||||
smb_handle() {
|
||||
config_get path $1 path
|
||||
if [ "$path" = "$2" ] ;then
|
||||
global=1
|
||||
fi
|
||||
}
|
||||
|
||||
chk_en() {
|
||||
config_get_bool autoshare $1 autoshare 1
|
||||
[ $autoshare -eq 0 ] && exit
|
||||
}
|
||||
|
||||
config_load samba4
|
||||
config_foreach chk_en samba4
|
||||
|
||||
device=`basename $DEVPATH`
|
||||
|
||||
case "$ACTION" in
|
||||
add)
|
||||
|
||||
case "$device" in
|
||||
sd*);;
|
||||
md*);;
|
||||
hd*);;
|
||||
mmcblk*);;
|
||||
*) return;;
|
||||
esac
|
||||
|
||||
path="/dev/$device"
|
||||
|
||||
wait_for_init
|
||||
|
||||
cat /proc/mounts | grep -v '/boot\|/opt' | while read j
|
||||
do
|
||||
str=${j%% *}
|
||||
if [ "$str" == $path ];then
|
||||
strr=${j#* }
|
||||
target=${strr%% *}
|
||||
global=0
|
||||
config_foreach smb_handle sambashare $target
|
||||
name=${target#*/mnt/}
|
||||
|
||||
if [ $global -eq 0 ] ;then
|
||||
echo -e "\n\nconfig sambashare" >> $config_file
|
||||
echo -e "\toption auto '1'" >> $config_file
|
||||
echo -e "\toption name '$name'" >> $config_file
|
||||
echo -e "\toption path '$target'" >> $config_file
|
||||
echo -e "\toption read_only 'no'" >> $config_file
|
||||
echo -e "\toption guest_ok 'yes'" >> $config_file
|
||||
echo -e "\toption create_mask '0666'" >> $config_file
|
||||
echo -e "\toption dir_mask '0777'" >> $config_file
|
||||
echo -e "\toption device '$device'" >> $config_file
|
||||
echo -e "\toption inherit_owner 'yes'" >> $config_file
|
||||
/etc/init.d/samba4 reload
|
||||
return
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
|
||||
remove)
|
||||
i=0
|
||||
while true
|
||||
do
|
||||
dev=`uci get samba4.@sambashare[$i].device`
|
||||
[ $? -ne 0 ] && break
|
||||
|
||||
[ "$dev" = "$device" ] && {
|
||||
auto=`uci get samba4.@sambashare[$i].auto`
|
||||
[ $auto = "1" ] && {
|
||||
mount_dir=`uci get samba4.@sambashare[$i].name`
|
||||
uci delete samba4.@sambashare[$i]
|
||||
uci commit
|
||||
/etc/init.d/samba4 reload
|
||||
return
|
||||
}
|
||||
}
|
||||
let i+=1
|
||||
done
|
||||
;;
|
||||
esac
|
||||
@@ -1,56 +0,0 @@
|
||||
[41;37mluci-app-aihelper: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-aliddns: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-autorepeater: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-autoshell: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-banmac-ipt: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-banmac-nft: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-broadbandacc: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-chongyoung: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-chongyoung2: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-ddnsto: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-diskman: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-dnscrypt-proxy2: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-dnsforwarder: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-dnsmasq-ipset: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-dogcom: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-fastnet: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-floatip: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-gpoint: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-gpsysupgrade: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-homebox: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-homebridge: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-iptvhelper: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-istoreenhance: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-istorego: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-kai: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-linkease: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-mac: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-miniproxy: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-mnh: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-mymind: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-nettask: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-nvr: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-onliner: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-pgyvpn: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-pikpak-webdav: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-poweroff: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-qos-emong: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-quickstart: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-rtbwmon: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-squid-adv: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-sunpanel: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-suselogin: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-switch-lan-play: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-systools: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-tasks: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-tcpdump: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-tencentcloud-cos: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-tencentddns: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-torbp: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-unishare: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-webviewdev: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-xjay: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-xunyou: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-yggdrasil: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-ympd: has no/multi config file(s), skipping...[0m
|
||||
[41;37mluci-app-zdinnav: has no/multi config file(s), skipping...[0m
|
||||
@@ -1,96 +0,0 @@
|
||||
[42;37mluci-app-adbyby-plus: ACL file has been generated.[0m
|
||||
[42;37mluci-app-arcadia: ACL file has been generated.[0m
|
||||
[42;37mluci-app-autoipsetadder: ACL file has been generated.[0m
|
||||
[42;37mluci-app-autoupdate: ACL file has been generated.[0m
|
||||
[42;37mluci-app-baidupcs-web: ACL file has been generated.[0m
|
||||
[42;37mluci-app-bridge: ACL file has been generated.[0m
|
||||
[42;37mluci-app-chinesesubfinder: ACL file has been generated.[0m
|
||||
[42;37mluci-app-codeserver: ACL file has been generated.[0m
|
||||
[42;37mluci-app-cpe: ACL file has been generated.[0m
|
||||
[42;37mluci-app-demon: ACL file has been generated.[0m
|
||||
[42;37mluci-app-dnspod: ACL file has been generated.[0m
|
||||
[42;37mluci-app-dpanel: ACL file has been generated.[0m
|
||||
[42;37mluci-app-drawio: ACL file has been generated.[0m
|
||||
[42;37mluci-app-dynv6: ACL file has been generated.[0m
|
||||
[42;37mluci-app-emby: ACL file has been generated.[0m
|
||||
[42;37mluci-app-excalidraw: ACL file has been generated.[0m
|
||||
[42;37mluci-app-fan: ACL file has been generated.[0m
|
||||
[42;37mluci-app-feishuvpn: ACL file has been generated.[0m
|
||||
[42;37mluci-app-forcedata: ACL file has been generated.[0m
|
||||
[42;37mluci-app-frps: ACL file has been generated.[0m
|
||||
[42;37mluci-app-gobinetmodem: ACL file has been generated.[0m
|
||||
[42;37mluci-app-gogs: ACL file has been generated.[0m
|
||||
[42;37mluci-app-heimdall: ACL file has been generated.[0m
|
||||
[42;37mluci-app-homeassistant: ACL file has been generated.[0m
|
||||
[42;37mluci-app-htreader: ACL file has been generated.[0m
|
||||
[42;37mluci-app-hypercpe: ACL file has been generated.[0m
|
||||
[42;37mluci-app-hypermodem: ACL file has been generated.[0m
|
||||
[42;37mluci-app-immich: ACL file has been generated.[0m
|
||||
[42;37mluci-app-ipv6clientfilter: ACL file has been generated.[0m
|
||||
[42;37mluci-app-istoredup: ACL file has been generated.[0m
|
||||
[42;37mluci-app-istorepanel: ACL file has been generated.[0m
|
||||
[42;37mluci-app-istorex: ACL file has been generated.[0m
|
||||
[42;37mluci-app-ittools: ACL file has been generated.[0m
|
||||
[42;37mluci-app-jackett: ACL file has been generated.[0m
|
||||
[42;37mluci-app-jellyfin: ACL file has been generated.[0m
|
||||
[42;37mluci-app-lanraragi: ACL file has been generated.[0m
|
||||
[42;37mluci-app-memos: ACL file has been generated.[0m
|
||||
[42;37mluci-app-mfun: ACL file has been generated.[0m
|
||||
[42;37mluci-app-mproxy: ACL file has been generated.[0m
|
||||
[42;37mluci-app-mtphotos: ACL file has been generated.[0m
|
||||
[42;37mluci-app-multiaccountdial: ACL file has been generated.[0m
|
||||
[42;37mluci-app-nastools: ACL file has been generated.[0m
|
||||
[42;37mluci-app-nat6-helper: ACL file has been generated.[0m
|
||||
[42;37mluci-app-natter: ACL file has been generated.[0m
|
||||
[42;37mluci-app-natter2: ACL file has been generated.[0m
|
||||
[42;37mluci-app-navidrome: ACL file has been generated.[0m
|
||||
[42;37mluci-app-nextcloud: ACL file has been generated.[0m
|
||||
[42;37mluci-app-nezhav1: ACL file has been generated.[0m
|
||||
[42;37mluci-app-npc: ACL file has been generated.[0m
|
||||
[42;37mluci-app-oneapi: ACL file has been generated.[0m
|
||||
[42;37mluci-app-openvpn-server: ACL file has been generated.[0m
|
||||
[42;37mluci-app-openvpn-server-client: ACL file has been generated.[0m
|
||||
[42;37mluci-app-openwebui: ACL file has been generated.[0m
|
||||
[42;37mluci-app-owntone: ACL file has been generated.[0m
|
||||
[42;37mluci-app-pcimodem: ACL file has been generated.[0m
|
||||
[42;37mluci-app-penpot: ACL file has been generated.[0m
|
||||
[42;37mluci-app-photoprism: ACL file has been generated.[0m
|
||||
[42;37mluci-app-plex: ACL file has been generated.[0m
|
||||
[42;37mluci-app-pppwn: ACL file has been generated.[0m
|
||||
[42;37mluci-app-pptp-server: ACL file has been generated.[0m
|
||||
[42;37mluci-app-pptpd: ACL file has been generated.[0m
|
||||
[42;37mluci-app-pve: ACL file has been generated.[0m
|
||||
[42;37mluci-app-routerdog: ACL file has been generated.[0m
|
||||
[42;37mluci-app-rtorrent: ACL file has been generated.[0m
|
||||
[42;37mluci-app-runmynas: ACL file has been generated.[0m
|
||||
[42;37mluci-app-school: ACL file has been generated.[0m
|
||||
[42;37mluci-app-serverchan: ACL file has been generated.[0m
|
||||
[42;37mluci-app-shadowrt: ACL file has been generated.[0m
|
||||
[42;37mluci-app-shanligong: ACL file has been generated.[0m
|
||||
[42;37mluci-app-shortcutmenu: ACL file has been generated.[0m
|
||||
[42;37mluci-app-siitwizard: ACL file has been generated.[0m
|
||||
[42;37mluci-app-smartinfo: ACL file has been generated.[0m
|
||||
[42;37mluci-app-spdmodem: ACL file has been generated.[0m
|
||||
[42;37mluci-app-speedtest-web: ACL file has been generated.[0m
|
||||
[42;37mluci-app-ssrserver-python: ACL file has been generated.[0m
|
||||
[42;37mluci-app-store: ACL file has been generated.[0m
|
||||
[42;37mluci-app-supervisord: ACL file has been generated.[0m
|
||||
[42;37mluci-app-synology: ACL file has been generated.[0m
|
||||
[42;37mluci-app-taskschedule: ACL file has been generated.[0m
|
||||
[42;37mluci-app-turboacc: ACL file has been generated.[0m
|
||||
[42;37mluci-app-typecho: ACL file has been generated.[0m
|
||||
[42;37mluci-app-ubuntu: ACL file has been generated.[0m
|
||||
[42;37mluci-app-ubuntu2: ACL file has been generated.[0m
|
||||
[42;37mluci-app-unblockmusic: ACL file has been generated.[0m
|
||||
[42;37mluci-app-unifi: ACL file has been generated.[0m
|
||||
[42;37mluci-app-uptimekuma: ACL file has been generated.[0m
|
||||
[42;37mluci-app-usbmodem: ACL file has been generated.[0m
|
||||
[42;37mluci-app-vaultwarden: ACL file has been generated.[0m
|
||||
[42;37mluci-app-vnt: ACL file has been generated.[0m
|
||||
[42;37mluci-app-webd: ACL file has been generated.[0m
|
||||
[42;37mluci-app-webvirtcloud: ACL file has been generated.[0m
|
||||
[42;37mluci-app-wifidog: ACL file has been generated.[0m
|
||||
[42;37mluci-app-wxedge: ACL file has been generated.[0m
|
||||
[42;37mluci-app-xteve: ACL file has been generated.[0m
|
||||
[42;37mluci-app-xunlei: ACL file has been generated.[0m
|
||||
[42;37mluci-app-xupnpd: ACL file has been generated.[0m
|
||||
@@ -1,251 +0,0 @@
|
||||
[43;37mluci-app-3cat: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-3ginfo-lite: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-3proxy: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-accesscontrol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-accesscontrol-plus: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-adguardhome: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-advancedplus: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-advancedsetting: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-airconnect: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-airplay2: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-alist: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-aliyundrive-webdav: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-alpha-config: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-alwaysonline: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-amlogic: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-amule: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ap-modem: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-apfree-wifidog: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-apinger: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-appfilter: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-argon-config: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-aria2: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-arpbind: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-at-socat: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-atcommands: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-atinout: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-autoreboot: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-babeld: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-bandix: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-beardropper: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-bitsrunlogin-go: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-bypass: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-caddy: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-campusnet: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cd8021x: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cellled: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cellularstatus: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-change-mac: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-chatgpt-web: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-chinadns-ng: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cifs: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cifs-mount: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-clash: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-clouddrive2: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cloudflarespeedtest: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cloudreve: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-control-timewol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-control-webrestriction: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-control-weburl: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-coredns: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cpu-perf: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cpu-status: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cpu-status-mini: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cpufreq: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cpulimit: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cqustdotnet: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-csshnpd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-cupsd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-dae: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-daed: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-daed-next: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ddns: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ddns-go: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-design-config: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-disks-info: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-dnsfilter: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-dnsleaktest: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-dnsproxy: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-docker: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-dockerman: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-domain-proxy: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-droidmodem: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-droidnet: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-dsvpn: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-dufs: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-easyconfig-transfer: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-easymesh: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-easytier: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-easyupdate: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-einat: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-eqos: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-eqosplus: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-fancontrol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-fchomo: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-fileassistant: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-filebrowser: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-fogvdn: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-frpc: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-fullconenat: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-glorytun-tcp: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-glorytun-udp: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-gost: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-gowebdav: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-gpioled: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-guest-wifi: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-haproxy-tcp: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-homeproxy: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-homeredirect: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ikoolproxy: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-interfaces-statistics: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-internet-detector: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-iperf: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-iperf3-server: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ipinfo: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ipsec-server: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ipsec-vpnd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-jederproxy: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-k3screenctrl: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-k3usb: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-kodexplorer: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ksmbd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-kucat-config: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-libreswan: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-lingtigameacc: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-lite-watchdog: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-log: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-lorawan-basicstation: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-lucky: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-macvlan: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mail: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mentohust: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mergerfs: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-microsocks: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-minieap: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mlvpn: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mmconfig: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-modem: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-modemband: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-modeminfo: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mosdns: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mptcp: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-msd_lite: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-music-remote-center: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mwan3-ledhelper: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mwan3helper: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-mwol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-my-dnshelper: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-n2n: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-natmap: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-natmapt: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-neko: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nekobox: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-netdata: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nfs: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nginx: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nginx-ha: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nginx-manager: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nginx-pingos: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ngrokc: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nikki: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-njitclient: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nodogsplash: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-nps: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-oaf: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-oled: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-openclash: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-openlist2: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-openvpn-client: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-oscam: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ota: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-package-manager: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-packagesync: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-packet-capture: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-parentcontrol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-partexp: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-passwall: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-passwall2: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-phtunnel: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-pingcontrol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-poweroffdevice: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-pppoe-relay: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-pppoe-server: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-pppoe-user: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ps3netsrv: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-public-ip-monitor: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-pushbot: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-qbittorrent: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-qiyougamebooster: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-qosmate: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ramfree: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-rclone: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-redsocks: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-rustdesk-server: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-samba4: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-scutclient: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-shadowsocks-rust: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-shutdown: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-smartdns: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-smartvpn: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-smbuser: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-sms-tool: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-sms-tool-js: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-smstools3: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-socat: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-softether: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-softethervpn: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-spotifyd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-sqm-autorate: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ss-redir: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ssr-mudb-server: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ssr-plus: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ssrust: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ssw: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-strongswan-swanctl: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-subconverter: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-switchtools: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-syncdial: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-syncthing: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-syscontrol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-sysuh3c: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-tailscale: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-tailscale-community: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-taskplan: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-telegrambot: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-temp-status: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-timecontrol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-timedreboot: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-timewol: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-tinyfilemanager: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-tn-lldpd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-tn-netports: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-transmission: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-trojan-server: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ttl: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-ua2f: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-unblockneteasemusic: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-upnp: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-usb-printer: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-uugamebooster: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-v2ray-server: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-verysync: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-vlmcsd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-vsftpd: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-wan-mac: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-watchcat: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-watchdog: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-webadmin: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-webdav: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-webrestriction: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-wechatpush: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-wifihistory: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-wizard: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-wolplus: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-wrtbwmon: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-xclient: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-xlnetacc: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-xray: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-xray-status: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-xwan: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-yt-dlp: has ACL file already, skipping...[0m
|
||||
[43;37mluci-app-zerotier: has ACL file already, skipping...[0m
|
||||
@@ -1,73 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ddns-scripts_aliyun
|
||||
PKG_VERSION:=1.0.3
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPLv2
|
||||
PKG_MAINTAINER:=Sense <sensec@gmail.com>
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ddns-scripts_aliyun
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=IP Addresses and Names
|
||||
TITLE:=DDNS extension for AliYun.com
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+ddns-scripts +wget-ssl +openssl-util
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/description
|
||||
Dynamic DNS Client scripts extension for AliYun.com
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(CP) ./*.sh $(PKG_BUILD_DIR)
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/preinst
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/ddns $(1)/usr/share/ddns/default
|
||||
$(INSTALL_BIN) $(CURDIR)/update_aliyun_com.sh $(1)/usr/lib/ddns
|
||||
$(INSTALL_DATA) $(CURDIR)/aliyun.com.json $(1)/usr/share/ddns/default
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/postinst
|
||||
#!/bin/sh
|
||||
# remove old services file entries
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
# and create new
|
||||
printf "%s\\t\\t%s\\n" '"aliyun.com"' '"update_aliyun_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services
|
||||
printf "%s\\t\\t%s\\n" '"aliyun.com"' '"update_aliyun_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6
|
||||
# on real system restart service if enabled
|
||||
[ -z "$${IPKG_INSTROOT}" ] && {
|
||||
/etc/init.d/ddns enabled && \
|
||||
/etc/init.d/ddns start >/dev/null 2>&1
|
||||
}
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_aliyun/prerm
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
# remove services file entries
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/aliyun\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ddns-scripts_aliyun))
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "aliyun.com",
|
||||
"ipv4": {
|
||||
"url": "update_aliyun_com.sh"
|
||||
},
|
||||
"ipv6": {
|
||||
"url": "update_aliyun_com.sh"
|
||||
}
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# 用于阿里云解析的DNS更新脚本
|
||||
# 2017-2018 Sense <sensec at gmail dot com>
|
||||
# 阿里云解析API文档 https://help.aliyun.com/document_detail/29739.html
|
||||
#
|
||||
# 本脚本由 dynamic_dns_functions.sh 内的函数 send_update() 调用
|
||||
#
|
||||
# 需要在 /etc/config/ddns 中设置的选项
|
||||
# option username - 阿里云API访问账号 Access Key ID。可通过 aliyun.com 帐号管理的 accesskeys 获取, 或者访问 https://ak-console.aliyun.com
|
||||
# option password - 阿里云API访问密钥 Access Key Secret
|
||||
# option domain - 完整的域名。建议主机与域名之间使用 @符号 分隔,否则将以第一个 .符号 之前的内容作为主机名
|
||||
#
|
||||
|
||||
# 检查传入参数
|
||||
[ -z "$username" ] && write_log 14 "配置错误!保存阿里云API访问账号的'用户名'不能为空"
|
||||
[ -z "$password" ] && write_log 14 "配置错误!保存阿里云API访问密钥的'密码'不能为空"
|
||||
|
||||
# 检查外部调用工具
|
||||
WGET_SSL='wget'
|
||||
[ -n "$WGET_SSL" ] || write_log 13 "使用阿里云API需要 GNU Wget 支持,请先安装"
|
||||
command -v sed >/dev/null 2>&1 || write_log 13 "使用阿里云API需要 sed 支持,请先安装"
|
||||
command -v openssl >/dev/null 2>&1 || write_log 13 "使用阿里云API需要 openssl-util 支持,请先安装"
|
||||
|
||||
# 包含用于解析 JSON 格式返回值的函数
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
# 变量声明
|
||||
local __HOST __DOMAIN __TYPE __URLBASE __CMDBASE __URLARGS __SEPARATOR __RECID
|
||||
[ $use_https -eq 0 ] && __URLBASE="http://alidns.aliyuncs.com/" || __URLBASE="https://alidns.aliyuncs.com/"
|
||||
__SEPARATOR="&"
|
||||
|
||||
# 从 $domain 分离主机和域名
|
||||
[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理
|
||||
[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式
|
||||
__HOST="${domain%%@*}"
|
||||
__DOMAIN="${domain#*@}"
|
||||
[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
|
||||
|
||||
# 设置记录类型
|
||||
[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
|
||||
|
||||
# 构造基本通信命令
|
||||
build_command() {
|
||||
__CMDBASE="$WGET_SSL --no-hsts -nv -t 1 -O $DATFILE -o $ERRFILE"
|
||||
# 绑定用于通信的主机/IP
|
||||
if [ -n "$bind_network" ]; then
|
||||
local bind_ip run_prog
|
||||
[ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6"
|
||||
eval "$run_prog bind_ip $bind_network" || \
|
||||
write_log 13 "无法使用 '$run_prog $bind_network' 获取本地IP地址 - 错误代码: '$?'"
|
||||
write_log 7 "强制使用IP '$bind_ip' 通信"
|
||||
__CMDBASE="$__CMDBASE --bind-address=$bind_ip"
|
||||
fi
|
||||
# 强制设定IP版本
|
||||
if [ $force_ipversion -eq 1 ]; then
|
||||
[ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6"
|
||||
fi
|
||||
# 设置CA证书参数
|
||||
if [ $use_https -eq 1 ]; then
|
||||
if [ "$cacert" = "IGNORE" ]; then
|
||||
__CMDBASE="$__CMDBASE --no-check-certificate"
|
||||
elif [ -f "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-certificate=${cacert}"
|
||||
elif [ -d "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-directory=${cacert}"
|
||||
elif [ -n "$cacert" ]; then
|
||||
write_log 14 "在 '$cacert' 中未找到用于 HTTPS 通信的有效证书"
|
||||
fi
|
||||
fi
|
||||
# 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误)
|
||||
[ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy"
|
||||
}
|
||||
|
||||
# 用于阿里云API的通信函数
|
||||
aliyun_transfer() {
|
||||
local __PARAM=$*
|
||||
local __CNT=0
|
||||
local __RUNPROG __ERR PID_SLEEP
|
||||
|
||||
[ $# -eq 0 ] && write_log 12 "'aliyun_transfer()' 出错 - 参数数量错误"
|
||||
|
||||
while : ; do
|
||||
build_Request $__PARAM
|
||||
__RUNPROG="$__CMDBASE '${__URLBASE}?${__URLARGS}'"
|
||||
|
||||
write_log 7 "#> $__RUNPROG"
|
||||
eval $__RUNPROG
|
||||
__ERR=$?
|
||||
[ $__ERR -eq 0 ] && return 0
|
||||
|
||||
write_log 3 "wget 错误代码: '$__ERR'"
|
||||
write_log 7 "$(cat $ERRFILE)"
|
||||
|
||||
if [ $VERBOSE -gt 1 ]; then
|
||||
write_log 4 "传输失败 - 详细模式: $VERBOSE - 出错后不再重试"
|
||||
return 1
|
||||
fi
|
||||
|
||||
__CNT=$(( $__CNT + 1 ))
|
||||
[ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && \
|
||||
write_log 14 "$retry_count 次重试后传输还是失败"
|
||||
|
||||
write_log 4 "传输失败 - $__CNT/$retry_count 在 $RETRY_SECONDS 秒后重试"
|
||||
sleep $RETRY_SECONDS &
|
||||
PID_SLEEP=$!
|
||||
wait $PID_SLEEP
|
||||
PID_SLEEP=0
|
||||
done
|
||||
}
|
||||
|
||||
# 百分号编码
|
||||
percentEncode() {
|
||||
if [ -z "${1//[A-Za-z0-9_.~-]/}" ]; then
|
||||
echo -n "$1"
|
||||
else
|
||||
local string=$1; local i=0; local ret chr
|
||||
while [ $i -lt ${#string} ]; do
|
||||
chr=${string:$i:1}
|
||||
[ -z "${chr#[^A-Za-z0-9_.~-]}" ] && chr=$(printf '%%%02X' "'$chr")
|
||||
ret="$ret$chr"
|
||||
i=$(( $i + 1 ))
|
||||
done
|
||||
echo -n "$ret"
|
||||
fi
|
||||
}
|
||||
|
||||
# 构造阿里云解析请求参数
|
||||
build_Request() {
|
||||
local args=$*; local string
|
||||
local HTTP_METHOD="GET"
|
||||
|
||||
# 添加请求参数
|
||||
__URLARGS=
|
||||
for string in $args; do
|
||||
case "${string%%=*}" in
|
||||
Format|TTL|Version|AccessKeyId|SignatureMethod|Timestamp|SignatureVersion|SignatureNonce|Signature) ;; # 过滤公共参数
|
||||
*) __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}");;
|
||||
esac
|
||||
done
|
||||
__URLARGS="${__URLARGS:1}"
|
||||
|
||||
# 附加公共参数
|
||||
string="Format=JSON"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="TTL=600";__URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="Version=2015-01-09"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="AccessKeyId=$username"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="SignatureMethod=HMAC-SHA1"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="Timestamp="$(date -u '+%Y-%m-%dT%H:%M:%SZ'); __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="SignatureVersion=1.0"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
string="SignatureNonce="$(cat '/proc/sys/kernel/random/uuid'); __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
|
||||
# 对请求参数进行排序,用于生成签名
|
||||
string=$(echo -n "$__URLARGS" | sed 's/\'"${__SEPARATOR}"'/\n/g' | sort | sed ':label; N; s/\n/\'"${__SEPARATOR}"'/g; b label')
|
||||
# 构造用于计算签名的字符串
|
||||
string="${HTTP_METHOD}${__SEPARATOR}"$(percentEncode "/")"${__SEPARATOR}"$(percentEncode "$string")
|
||||
# 字符串计算签名HMAC值
|
||||
local signature=$(echo -n "$string" | openssl dgst -sha1 -hmac "${password}&" -binary)
|
||||
# HMAC值编码成字符串,得到签名值
|
||||
signature=$(echo -n "$signature" | openssl base64)
|
||||
|
||||
# 附加签名参数
|
||||
string="Signature=$signature"; __URLARGS="$__URLARGS${__SEPARATOR}"$(percentEncode "${string%%=*}")"="$(percentEncode "${string#*=}")
|
||||
}
|
||||
|
||||
# 添加解析记录
|
||||
add_domain() {
|
||||
local value
|
||||
aliyun_transfer "Action=AddDomainRecord" "DomainName=${__DOMAIN}" "RR=${__HOST}" "Type=${__TYPE}" "Value=${__IP}" || write_log 14 "服务器通信失败"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var value "RecordId"
|
||||
[ -z "$value" ] && write_log 14 "添加新解析记录失败"
|
||||
write_log 7 "添加新解析记录成功"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 修改解析记录
|
||||
update_domain() {
|
||||
local value
|
||||
aliyun_transfer "Action=UpdateDomainRecord" "RecordId=${__RECID}" "RR=${__HOST}" "Type=${__TYPE}" "Value=${__IP}" || write_log 14 "服务器通信失败"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var value "RecordId"
|
||||
[ -z "$value" ] && write_log 14 "修改解析记录失败"
|
||||
write_log 7 "修改解析记录成功"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 启用解析记录
|
||||
enable_domain() {
|
||||
local value
|
||||
aliyun_transfer "Action=SetDomainRecordStatus" "RecordId=${__RECID}" "Status=Enable" || write_log 14 "服务器通信失败"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var value "Status"
|
||||
[ "$value" != "Enable" ] && write_log 14 "启用解析记录失败"
|
||||
write_log 7 "启用解析记录成功"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 获取子域名解析记录列表
|
||||
describe_domain() {
|
||||
local count value; local ret=0
|
||||
aliyun_transfer "Action=DescribeSubDomainRecords" "SubDomain=${__HOST}.${__DOMAIN}" "DomainName=${__DOMAIN}" "Line=default" || write_log 14 "服务器通信失败"
|
||||
write_log 7 "获取到解析记录: $(cat "$DATFILE" 2> /dev/null)"
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_get_var count "TotalCount"
|
||||
if [ $count -eq 0 ]; then
|
||||
write_log 7 "解析记录不存在"
|
||||
ret=1
|
||||
else
|
||||
local i=1;
|
||||
while [ $i -le $count ]; do
|
||||
json_cleanup; json_load "$(cat "$DATFILE" 2> /dev/null)" >/dev/null 2>&1
|
||||
json_select "DomainRecords" >/dev/null 2>&1
|
||||
json_select "Record" >/dev/null 2>&1
|
||||
json_select $i >/dev/null 2>&1
|
||||
i=$(( $i + 1 ))
|
||||
json_get_var value "Type"
|
||||
if [ "$value" != "${__TYPE}" ]; then
|
||||
write_log 7 "当前解析类型: ${__TYPE}, 获得不匹配类型: $value"
|
||||
ret=1; continue
|
||||
else
|
||||
ret=0
|
||||
json_get_var __RECID "RecordId"
|
||||
write_log 7 "获得解析记录ID: ${__RECID}, 类型: $value"
|
||||
json_get_var value "Locked"
|
||||
[ $value -ne 0 ] && write_log 14 "解析记录被锁定"
|
||||
json_get_var value "Status"
|
||||
[ "$value" != "ENABLE" ] && ret=$(( $ret | 2 )) && write_log 7 "解析记录被禁用"
|
||||
json_get_var value "Value"
|
||||
[ "$value" != "${__IP}" ] && ret=$(( $ret | 4 )) && write_log 7 "地址需要修改"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
|
||||
build_command
|
||||
describe_domain
|
||||
ret=$?
|
||||
if [ $ret -eq 1 ]; then
|
||||
sleep 3 && add_domain
|
||||
else
|
||||
[ $(( $ret & 2 )) -ne 0 ] && sleep 3 && enable_domain
|
||||
[ $(( $ret & 4 )) -ne 0 ] && sleep 3 && update_domain
|
||||
fi
|
||||
|
||||
return 0
|
||||
@@ -1,78 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ddns-scripts_dnspod
|
||||
PKG_VERSION:=1.0.2
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPLv2
|
||||
PKG_MAINTAINER:=Small_5
|
||||
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ddns-scripts_dnspod
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=IP Addresses and Names
|
||||
TITLE:=DDNS extension for Dnspod.com/Dnspod.cn
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+ddns-scripts +wget-ssl +ca-bundle
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/description
|
||||
Dynamic DNS Client scripts extension for Dnspod.com/Dnspod.cn
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/preinst
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib/ddns $(1)/usr/share/ddns/default
|
||||
$(INSTALL_BIN) $(CURDIR)/*.sh $(1)/usr/lib/ddns
|
||||
$(INSTALL_DATA) $(CURDIR)/*.json $(1)/usr/share/ddns/default
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/postinst
|
||||
#!/bin/sh
|
||||
# remove old services file entries
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
# and create new
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.com"' '"update_dnspod_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.cn"' '"update_dnspod_cn.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.com"' '"update_dnspod_com.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6
|
||||
printf "%s\\t\\t%s\\n" '"dnspod.cn"' '"update_dnspod_cn.sh"' >> $${IPKG_INSTROOT}/etc/ddns/services_ipv6
|
||||
# on real system restart service if enabled
|
||||
[ -z "$${IPKG_INSTROOT}" ] && {
|
||||
/etc/init.d/ddns enabled && \
|
||||
/etc/init.d/ddns start >/dev/null 2>&1
|
||||
}
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
define Package/ddns-scripts_dnspod/prerm
|
||||
#!/bin/sh
|
||||
# if NOT run buildroot then stop service
|
||||
[ -z "$${IPKG_INSTROOT}" ] && /etc/init.d/ddns stop >/dev/null 2>&1
|
||||
# remove services file entries
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.com/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
/bin/sed -i '/dnspod\.cn/d' $${IPKG_INSTROOT}/etc/ddns/services_ipv6 >/dev/null 2>&1
|
||||
exit 0 # suppress errors
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ddns-scripts_dnspod))
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "dnspod.com",
|
||||
"ipv4": {
|
||||
"url": "update_dnspod_cn.sh"
|
||||
},
|
||||
"ipv6": {
|
||||
"url": "update_dnspod_cn.sh"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "dnspod.com",
|
||||
"ipv4": {
|
||||
"url": "update_dnspod_com.sh"
|
||||
},
|
||||
"ipv6": {
|
||||
"url": "update_dnspod_com.sh"
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#检查传入参数
|
||||
[ -z "$username" ] && write_log 14 "Configuration error! [User name] cannot be empty"
|
||||
[ -z "$password" ] && write_log 14 "Configuration error! [Password] cannot be empty"
|
||||
|
||||
#检查外部调用工具
|
||||
WGET_SSL='wget'
|
||||
[ -n "$WGET_SSL" ] || write_log 13 "GNU Wget support is required to use dnspod API. Please install first"
|
||||
|
||||
# 变量声明
|
||||
local __URLBASE __HOST __DOMAIN __TYPE __CMDBASE __POST __POST1 __RECIP __RECID __value __TTL
|
||||
__URLBASE="https://dnsapi.cn/"
|
||||
|
||||
# 从 $domain 分离主机和域名
|
||||
[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理
|
||||
[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式
|
||||
__HOST="${domain%%@*}"
|
||||
__DOMAIN="${domain#*@}"
|
||||
[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
|
||||
|
||||
# 设置记录类型
|
||||
[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
|
||||
|
||||
# 构造基本通信命令
|
||||
build_command() {
|
||||
__CMDBASE="$WGET_SSL --no-hsts -nv -t 1 -O $DATFILE -o $ERRFILE"
|
||||
# 绑定用于通信的主机/IP
|
||||
if [ -n "$bind_network" ]; then
|
||||
local bind_ip run_prog
|
||||
[ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6"
|
||||
eval "$run_prog bind_ip $bind_network" || \
|
||||
write_log 13 "Unable to get local IP address with '$run_prog $ bind_network' - error code: '$?'"
|
||||
write_log 7 "Forced use of IP '$bind_ip' communication"
|
||||
__CMDBASE="$__CMDBASE --bind-address=$bind_ip"
|
||||
fi
|
||||
# 强制设定IP版本
|
||||
if [ $force_ipversion -eq 1 ]; then
|
||||
[ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6"
|
||||
fi
|
||||
# 设置CA证书参数
|
||||
if [ $use_https -eq 1 ]; then
|
||||
if [ "$cacert" = "IGNORE" ]; then
|
||||
__CMDBASE="$__CMDBASE --no-check-certificate"
|
||||
elif [ -f "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-certificate=${cacert}"
|
||||
elif [ -d "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-directory=${cacert}"
|
||||
elif [ -n "$cacert" ]; then
|
||||
write_log 14 "A valid certificate for HTTPS communication was not found in '$cacert'"
|
||||
fi
|
||||
fi
|
||||
# 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误)
|
||||
[ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy"
|
||||
__CMDBASE="$__CMDBASE --post-data"
|
||||
}
|
||||
|
||||
# 用于Dnspod API的通信函数
|
||||
dnspod_transfer() {
|
||||
local __A=$1
|
||||
local __CNT=0
|
||||
local __ERR=0
|
||||
local __B PID_SLEEP
|
||||
case "$__A" in
|
||||
0)
|
||||
__B="$__CMDBASE '$__POST' ${__URLBASE}Record.List"
|
||||
;;
|
||||
1)
|
||||
__B="$__CMDBASE '$__POST1' ${__URLBASE}Record.Create"
|
||||
;;
|
||||
2)
|
||||
__B="$__CMDBASE '$__POST1&record_id=$__RECID&ttl=$__TTL' ${__URLBASE}Record.Modify"
|
||||
;;
|
||||
esac
|
||||
|
||||
while : ; do
|
||||
write_log 7 "#> $__B"
|
||||
eval $__B
|
||||
__ERR=`jsonfilter -i $DATFILE -e "@.status.code"`
|
||||
|
||||
[ $__ERR -eq 1 ] && return 0
|
||||
[ $__A -eq 0 ] && [ $__ERR -eq 10 ] && return 0
|
||||
write_log 3 "Error message:[$(jsonfilter -i $DATFILE -e "@.status.message")]"
|
||||
|
||||
if [ $VERBOSE -gt 1 ]; then
|
||||
write_log 4 "Transfer failed - detailed mode: $VERBOSE - Do not try again after an error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
__CNT=$(( $__CNT + 1 ))
|
||||
[ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && write_log 14 "Transfer failed after $retry_count retries"
|
||||
|
||||
write_log 4 "Transfer failed - $__CNT Try again in $RETRY_SECONDS seconds"
|
||||
sleep $RETRY_SECONDS &
|
||||
PID_SLEEP=$!
|
||||
wait $PID_SLEEP
|
||||
PID_SLEEP=0
|
||||
done
|
||||
}
|
||||
|
||||
#添加解析记录
|
||||
add_domain() {
|
||||
dnspod_transfer 1
|
||||
write_log 7 "Add new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#修改解析记录
|
||||
update_domain() {
|
||||
dnspod_transfer 2
|
||||
write_log 7 "Modify new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP],[TTL:$__TTL] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#获取域名解析记录
|
||||
describe_domain() {
|
||||
ret=0
|
||||
__POST="login_token=$username,$password&format=json&domain=$__DOMAIN&sub_domain=$__HOST&record_type=$__TYPE"
|
||||
__POST1="$__POST&value=$__IP&record_type=$__TYPE&record_line_id=0"
|
||||
dnspod_transfer 0
|
||||
__TMP=`jsonfilter -i $DATFILE -e "@.records[@.type!='NS']"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.name"`
|
||||
if [ "$__value" == "" ]; then
|
||||
write_log 7 "Parsing record:[${__HOST}.${__DOMAIN}] does not exist"
|
||||
ret=1
|
||||
else
|
||||
__RECID=`jsonfilter -s "$__TMP" -e "@.id"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.type"`
|
||||
__TTL=`jsonfilter -s "$__TMP" -e "@.ttl"`
|
||||
write_log 7 "Get parsing recordID:[$__RECID]"
|
||||
if [ "$__value" != "$__TYPE" ]; then
|
||||
write_log 7 "Current parsing [type:$__TYPE], get mismatched [type:$__value]"
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
else
|
||||
__RECIP=`jsonfilter -s "$__TMP" -e "@.value"`
|
||||
if [ "$__RECIP" != "$__IP" ]; then
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
build_command
|
||||
describe_domain
|
||||
if [ $ret == 1 ];then
|
||||
sleep 3 && add_domain
|
||||
elif [ $ret == 2 ];then
|
||||
sleep 3 && update_domain
|
||||
else
|
||||
write_log 7 "Local IP:[$__IP] parsing records IP:[$__RECIP] address does not need to be modified"
|
||||
fi
|
||||
|
||||
return 0
|
||||
@@ -1,155 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#检查传入参数
|
||||
[ -z "$username" ] && write_log 14 "Configuration error! [User name] cannot be empty"
|
||||
[ -z "$password" ] && write_log 14 "Configuration error! [Password] cannot be empty"
|
||||
|
||||
#检查外部调用工具
|
||||
WGET_SSL='wget'
|
||||
[ -n "$WGET_SSL" ] || write_log 13 "GNU Wget support is required to use dnspod API. Please install first"
|
||||
|
||||
# 变量声明
|
||||
local __URLBASE __HOST __DOMAIN __TYPE __CMDBASE __POST __POST1 __RECIP __RECID __value __TTL
|
||||
__URLBASE="https://api.dnspod.com/"
|
||||
|
||||
# 从 $domain 分离主机和域名
|
||||
[ "${domain:0:2}" == "@." ] && domain="${domain/./}" # 主域名处理
|
||||
[ "$domain" == "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式
|
||||
__HOST="${domain%%@*}"
|
||||
__DOMAIN="${domain#*@}"
|
||||
[ -z "$__HOST" -o "$__HOST" == "$__DOMAIN" ] && __HOST="@"
|
||||
|
||||
# 设置记录类型
|
||||
[ $use_ipv6 -eq 0 ] && __TYPE="A" || __TYPE="AAAA"
|
||||
|
||||
# 构造基本通信命令
|
||||
build_command() {
|
||||
__CMDBASE="$WGET_SSL --no-hsts -nv -t 1 -O $DATFILE -o $ERRFILE"
|
||||
# 绑定用于通信的主机/IP
|
||||
if [ -n "$bind_network" ]; then
|
||||
local bind_ip run_prog
|
||||
[ $use_ipv6 -eq 0 ] && run_prog="network_get_ipaddr" || run_prog="network_get_ipaddr6"
|
||||
eval "$run_prog bind_ip $bind_network" || \
|
||||
write_log 13 "Unable to get local IP address with '$run_prog $ bind_network' - error code: '$?'"
|
||||
write_log 7 "Forced use of IP '$bind_ip' communication"
|
||||
__CMDBASE="$__CMDBASE --bind-address=$bind_ip"
|
||||
fi
|
||||
# 强制设定IP版本
|
||||
if [ $force_ipversion -eq 1 ]; then
|
||||
[ $use_ipv6 -eq 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6"
|
||||
fi
|
||||
# 设置CA证书参数
|
||||
if [ $use_https -eq 1 ]; then
|
||||
if [ "$cacert" = "IGNORE" ]; then
|
||||
__CMDBASE="$__CMDBASE --no-check-certificate"
|
||||
elif [ -f "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-certificate=${cacert}"
|
||||
elif [ -d "$cacert" ]; then
|
||||
__CMDBASE="$__CMDBASE --ca-directory=${cacert}"
|
||||
elif [ -n "$cacert" ]; then
|
||||
write_log 14 "A valid certificate for HTTPS communication was not found in '$cacert'"
|
||||
fi
|
||||
fi
|
||||
# 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误)
|
||||
[ -z "$proxy" ] && __CMDBASE="$__CMDBASE --no-proxy"
|
||||
__CMDBASE="$__CMDBASE --post-data"
|
||||
}
|
||||
|
||||
# 用于Dnspod API的通信函数
|
||||
dnspod_transfer() {
|
||||
local __A=$1
|
||||
local __CNT=0
|
||||
local __ERR=0
|
||||
local __B PID_SLEEP
|
||||
case "$__A" in
|
||||
0)
|
||||
__B="$__CMDBASE '$__POST' ${__URLBASE}Record.List"
|
||||
;;
|
||||
1)
|
||||
__B="$__CMDBASE '$__POST1' ${__URLBASE}Record.Create"
|
||||
;;
|
||||
2)
|
||||
__B="$__CMDBASE '$__POST1&record_id=$__RECID&ttl=$__TTL' ${__URLBASE}Record.Modify"
|
||||
;;
|
||||
esac
|
||||
|
||||
while : ; do
|
||||
write_log 7 "#> $__B"
|
||||
eval $__B
|
||||
__ERR=`jsonfilter -i $DATFILE -e "@.status.code"`
|
||||
|
||||
[ $__ERR -eq 1 ] && return 0
|
||||
[ $__A -eq 0 ] && [ $__ERR -eq 10 ] && return 0
|
||||
write_log 3 "Error message:[$(jsonfilter -i $DATFILE -e "@.status.message")]"
|
||||
|
||||
if [ $VERBOSE -gt 1 ]; then
|
||||
write_log 4 "Transfer failed - detailed mode: $VERBOSE - Do not try again after an error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
__CNT=$(( $__CNT + 1 ))
|
||||
[ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && write_log 14 "Transfer failed after $retry_count retries"
|
||||
|
||||
write_log 4 "Transfer failed - $__CNT Try again in $RETRY_SECONDS seconds"
|
||||
sleep $RETRY_SECONDS &
|
||||
PID_SLEEP=$!
|
||||
wait $PID_SLEEP
|
||||
PID_SLEEP=0
|
||||
done
|
||||
}
|
||||
|
||||
#添加解析记录
|
||||
add_domain() {
|
||||
dnspod_transfer 1
|
||||
write_log 7 "Add new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#修改解析记录
|
||||
update_domain() {
|
||||
dnspod_transfer 2
|
||||
write_log 7 "Modify new parsing record [${__HOST}.${__DOMAIN}],[type:$__TYPE],[ip:$__IP],[TTL:$__TTL] successfully!"
|
||||
return 0
|
||||
}
|
||||
|
||||
#获取域名解析记录
|
||||
describe_domain() {
|
||||
ret=0
|
||||
__POST="login_token=$username,$password&format=json&domain=$__DOMAIN&sub_domain=$__HOST&record_type=$__TYPE"
|
||||
__POST1="$__POST&value=$__IP&record_type=$__TYPE&record_line_id=0"
|
||||
dnspod_transfer 0
|
||||
__TMP=`jsonfilter -i $DATFILE -e "@.records[@.type!='NS']"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.name"`
|
||||
if [ "$__value" == "" ]; then
|
||||
write_log 7 "Parsing record:[${__HOST}.${__DOMAIN}] does not exist"
|
||||
ret=1
|
||||
else
|
||||
__RECID=`jsonfilter -s "$__TMP" -e "@.id"`
|
||||
__value=`jsonfilter -s "$__TMP" -e "@.type"`
|
||||
__TTL=`jsonfilter -s "$__TMP" -e "@.ttl"`
|
||||
write_log 7 "Get parsing recordID:[$__RECID]"
|
||||
if [ "$__value" != "$__TYPE" ]; then
|
||||
write_log 7 "Current parsing [type:$__TYPE], get mismatched [type:$__value]"
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
else
|
||||
__RECIP=`jsonfilter -s "$__TMP" -e "@.value"`
|
||||
if [ "$__RECIP" != "$__IP" ]; then
|
||||
write_log 7 "Address needs to be modified, local address:[$__IP]"
|
||||
ret=2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
build_command
|
||||
describe_domain
|
||||
if [ $ret == 1 ];then
|
||||
sleep 3 && add_domain
|
||||
elif [ $ret == 2 ];then
|
||||
sleep 3 && update_domain
|
||||
else
|
||||
write_log 7 "Local IP:[$__IP] parsing records IP:[$__RECIP] address does not need to be modified"
|
||||
fi
|
||||
|
||||
return 0
|
||||
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2016-2023 GitHub
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=default-settings
|
||||
PKG_RELEASE:=1
|
||||
PKG_LICENSE:=GPLv3
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/default-settings
|
||||
SECTION:=luci
|
||||
CATEGORY:=LuCI
|
||||
TITLE:=LuCI support for Default Settings
|
||||
PKGARCH:=all
|
||||
DEPENDS:= +luci-compat +@LUCI_LANG_zh-cn +@LUCI_LANG_zh_Hans +@LUCI_LANG_en
|
||||
endef
|
||||
|
||||
define Package/default-settings/description
|
||||
Language Support Packages.
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/default-settings/install
|
||||
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||
$(INSTALL_BIN) ./files/zzz-default-settings $(1)/etc/uci-defaults/99-default-settings
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
|
||||
po2lmo ./po/zh-cn/default.po $(1)/usr/lib/lua/luci/i18n/default.zh-cn.lmo
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,default-settings))
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
uci -q batch <<-EOF
|
||||
set system.@system[0].timezone='CST-8'
|
||||
set system.@system[0].zonename='Asia/Shanghai'
|
||||
|
||||
delete system.ntp.server
|
||||
add_list system.ntp.server='ntp1.aliyun.com'
|
||||
add_list system.ntp.server='ntp.tencent.com'
|
||||
add_list system.ntp.server='ntp.ntsc.ac.cn'
|
||||
add_list system.ntp.server='time.apple.com'
|
||||
EOF
|
||||
uci commit system
|
||||
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/mwan.htm
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/upnp.htm
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/ddns.htm
|
||||
rm -f /usr/lib/lua/luci/view/admin_status/index/minidlna.htm
|
||||
|
||||
rm -f /www/luci-static/resources/view/status/include/70_ddns.js
|
||||
rm -f /www/luci-static/resources/view/status/include/80_upnp.js
|
||||
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/aria2.lua
|
||||
sed -i 's/services/nas/g' /usr/lib/lua/luci/view/aria2/overview_status.htm
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/hd_idle.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/samba.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/samba4.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/minidlna.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/transmission.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/mjpg-streamer.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/p910nd.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/usb_printer.lua
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/xunlei.lua
|
||||
sed -i 's/services/nas/g' /usr/lib/lua/luci/view/minidlna_status.htm
|
||||
|
||||
sed -i 's/\"services\"/\"nas\"/g' /usr/share/luci/menu.d/luci-app-samba4.json
|
||||
|
||||
sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/opkg/distfeeds.conf
|
||||
sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/apk/repositories.d/distfeeds.list
|
||||
sed -i 's/root::0:0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow
|
||||
sed -i 's/root:::0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow
|
||||
|
||||
sed -i "s/# //g" /etc/opkg/distfeeds.conf
|
||||
sed -i '/helloworld/d' /etc/opkg/distfeeds.conf
|
||||
sed -i '/openwrt_luci/ { s/snapshots/releases\/18.06.9/g; }' /etc/opkg/distfeeds.conf
|
||||
|
||||
sed -i '/check_signature/d' /etc/opkg.conf
|
||||
|
||||
sed -i '/REDIRECT --to-ports 53/d' /etc/firewall.user
|
||||
|
||||
sed -i '/DISTRIB_REVISION/d' /etc/openwrt_release
|
||||
echo "DISTRIB_REVISION='R26.02.20'" >> /etc/openwrt_release
|
||||
sed -i '/DISTRIB_DESCRIPTION/d' /etc/openwrt_release
|
||||
echo "DISTRIB_DESCRIPTION='LEDE '" >> /etc/openwrt_release
|
||||
|
||||
sed -i '/OPENWRT_RELEASE/d' /usr/lib/os-release
|
||||
echo 'OPENWRT_RELEASE="LEDE R26.02.20"' >> /usr/lib/os-release
|
||||
|
||||
sed -i '/log-facility/d' /etc/dnsmasq.conf
|
||||
echo "log-facility=/dev/null" >> /etc/dnsmasq.conf
|
||||
|
||||
rm -rf /tmp/luci-modulecache/
|
||||
rm -f /tmp/luci-indexcache
|
||||
|
||||
exit 0
|
||||
@@ -1,70 +0,0 @@
|
||||
msgid "Swap"
|
||||
msgstr "虚拟内存"
|
||||
|
||||
msgid "Processor"
|
||||
msgstr "处理器"
|
||||
|
||||
msgid "Architecture"
|
||||
msgstr "架构"
|
||||
|
||||
msgid "CPU Temperature"
|
||||
msgstr "CPU 温度"
|
||||
|
||||
msgid "CPU Info"
|
||||
msgstr "CPU 信息"
|
||||
|
||||
msgid "CPU Model"
|
||||
msgstr "处理器型号"
|
||||
|
||||
msgid "CPU usage"
|
||||
msgstr "CPU 使用率"
|
||||
|
||||
msgid "CPU frequency"
|
||||
msgstr "CPU 频率"
|
||||
|
||||
msgid "RAM frequency"
|
||||
msgstr "RAM 频率"
|
||||
|
||||
msgid "Flash Size"
|
||||
msgstr "闪存大小"
|
||||
|
||||
msgid "Free Memory"
|
||||
msgstr "释放内存"
|
||||
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "ZRam Settings"
|
||||
msgstr "ZRam 设置"
|
||||
|
||||
msgid "ZRam Compression Algorithm"
|
||||
msgstr "ZRam 压缩算法"
|
||||
|
||||
msgid "ZRam Compression Streams"
|
||||
msgstr "ZRam 压缩数据流线程数"
|
||||
|
||||
msgid "ZRam Size"
|
||||
msgstr "ZRam 大小"
|
||||
|
||||
msgid "Size of the ZRam device in megabytes"
|
||||
msgstr "划分给 ZRam 分区的内存大小(MB),推荐留空由系统自动管理"
|
||||
|
||||
msgid "Number of parallel threads used for compression"
|
||||
msgstr "用于压缩内存数据的CPU并发线程数"
|
||||
|
||||
msgid "Force 40MHz mode"
|
||||
msgstr "强制 40MHz 频宽"
|
||||
|
||||
msgid ""
|
||||
"Always use 40MHz channels even if the secondary channel overlaps. Using this "
|
||||
"option does not comply with IEEE 802.11n-2009!"
|
||||
msgstr "强制启用 40MHz 频宽并忽略辅助信道重叠。此选项可能不兼容某些无线硬件导致无法启用!"
|
||||
|
||||
msgid "Disassociate On Low Acknowledgement"
|
||||
msgstr "弱信号剔除"
|
||||
|
||||
msgid "Allow AP mode to disconnect STAs based on low ACK condition"
|
||||
msgstr "允许 AP 模式基于低 ACK 条件判断剔除弱信号的客户端"
|
||||
@@ -1,26 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=fibocom-dial
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/fibocom-dial
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Fibocom Dial
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Package/fibocom-dial/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fibocom-dial $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fibo_qmimsg_server $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/multi-pdn-manager $(1)/usr/bin
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,fibocom-dial))
|
||||
@@ -1,275 +0,0 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
|
||||
#ifdef CONFIG_GOBINET
|
||||
|
||||
// IOCTL to generate a client ID for this service type
|
||||
#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1
|
||||
|
||||
// IOCTL to get the VIDPID of the device
|
||||
#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2
|
||||
|
||||
// IOCTL to get the MEID of the device
|
||||
#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3
|
||||
|
||||
static int GobiNetSendQMI(PQCQMIMSG pRequest)
|
||||
{
|
||||
int ret, fd;
|
||||
|
||||
static int send_count = 0;
|
||||
fd = qmiclientId[pRequest->QMIHdr.QMIType];
|
||||
|
||||
if (fd <= 0) {
|
||||
dbg_time("%s QMIType: %d has no clientID", __func__,
|
||||
pRequest->QMIHdr.QMIType);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Always ready to write
|
||||
re_write:
|
||||
if (1 == 1) {
|
||||
ssize_t nwrites =
|
||||
le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR);
|
||||
ret = write(fd, &pRequest->MUXMsg, nwrites);
|
||||
if (ret == nwrites)
|
||||
{
|
||||
ret = 0;
|
||||
send_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_count++;
|
||||
dbg_time("%s write=%d, errno: %d (%s) send_count %d", __func__, ret, errno, strerror(errno), send_count);
|
||||
if (send_count < 3)
|
||||
{
|
||||
sleep(1);
|
||||
goto re_write;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int GobiNetGetClientID(const char *qcqmi, UCHAR QMIType)
|
||||
{
|
||||
int ClientId;
|
||||
ClientId = open(qcqmi, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (ClientId == -1) {
|
||||
dbg_time("failed to open %s, errno: %d (%s)", qcqmi, errno,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(ClientId, IOCTL_QMI_GET_SERVICE_FILE, QMIType) != 0) {
|
||||
dbg_time("failed to get ClientID for 0x%02x errno: %d (%s)", QMIType,
|
||||
errno, strerror(errno));
|
||||
close(ClientId);
|
||||
ClientId = 0;
|
||||
}
|
||||
|
||||
dbg_time("%s: QMIType = %d clientid %d", __func__, QMIType, ClientId);
|
||||
|
||||
switch (QMIType) {
|
||||
case QMUX_TYPE_WDS:
|
||||
dbg_time("Get clientWDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_DMS:
|
||||
dbg_time("Get clientDMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_NAS:
|
||||
dbg_time("Get clientNAS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_QOS:
|
||||
dbg_time("Get clientQOS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WMS:
|
||||
dbg_time("Get clientWMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_PDS:
|
||||
dbg_time("Get clientPDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_UIM:
|
||||
dbg_time("Get clientUIM = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WDS_ADMIN:
|
||||
dbg_time("Get clientWDA = %d", ClientId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ClientId;
|
||||
}
|
||||
|
||||
static int GobiNetDeInit(void)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) {
|
||||
if (qmiclientId[i] != 0) {
|
||||
close(qmiclientId[i]);
|
||||
qmiclientId[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void *GobiNetThread(void *pData)
|
||||
{
|
||||
PROFILE_T *profile = (PROFILE_T *)pData;
|
||||
const char *qcqmi = (const char *)profile->qmichannel;
|
||||
int wait_for_request_quit = 0;
|
||||
dbg_time("%s %d", __func__, __LINE__);
|
||||
if (profile->ipv4_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
|
||||
if (profile->ipv6_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS);
|
||||
qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS);
|
||||
qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS);
|
||||
qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM);
|
||||
// qmiclientId[QMUX_TYPE_WDS_ADMIN] =
|
||||
// GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN);
|
||||
|
||||
//if ((qmiclientId[QMUX_TYPE_WDS] == 0) && (qmiclientId[QMUX_TYPE_WDS_IPV6] == 0)) /*|| (clientWDA == -1)*/ {
|
||||
|
||||
if ((qmiclientId[QMUX_TYPE_DMS] == 0) ||
|
||||
(qmiclientId[QMUX_TYPE_NAS] == 0) ||
|
||||
(qmiclientId[QMUX_TYPE_UIM] == 0) ||
|
||||
(profile->ipv4_flag ? ((qmiclientId[QMUX_TYPE_WDS] == 0) ? 1 : 0):0)||
|
||||
(profile->ipv6_flag ? ((qmiclientId[QMUX_TYPE_WDS_IPV6] == 0) ? 1 : 0):0))
|
||||
{
|
||||
GobiNetDeInit();
|
||||
dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno,strerror(errno));
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);
|
||||
|
||||
while (1) {
|
||||
struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}};
|
||||
int ne, ret, nevents = 1;
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) {
|
||||
if (qmiclientId[i] != 0) {
|
||||
pollfds[nevents].fd = qmiclientId[i];
|
||||
pollfds[nevents].events = POLLIN;
|
||||
pollfds[nevents].revents = 0;
|
||||
nevents++;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1);
|
||||
} while ((ret < 0) && (errno == EINTR));
|
||||
|
||||
if (ret == 0 && wait_for_request_quit) {
|
||||
QmiThreadRecvQMI(
|
||||
NULL); // main thread may pending on QmiThreadSendQMI()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
for (ne = 0; ne < nevents; ne++) {
|
||||
int fd = pollfds[ne].fd;
|
||||
short revents = pollfds[ne].revents;
|
||||
|
||||
if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||
dbg_time("%s poll err/hup/inval", __func__);
|
||||
dbg_time("epoll fd = %d, events = 0x%04x", fd, revents);
|
||||
if (fd == qmidevice_control_fd[1]) {
|
||||
} else {
|
||||
}
|
||||
if (revents & (POLLERR | POLLHUP | POLLNVAL))
|
||||
goto __GobiNetThread_quit;
|
||||
}
|
||||
if ((revents & POLLIN) == 0)
|
||||
continue;
|
||||
|
||||
if (fd == qmidevice_control_fd[1]) {
|
||||
int triger_event;
|
||||
if (read(fd, &triger_event, sizeof(triger_event)) ==
|
||||
sizeof(triger_event)) {
|
||||
// DBG("triger_event = 0x%x", triger_event);
|
||||
switch (triger_event) {
|
||||
case RIL_REQUEST_QUIT:
|
||||
goto __GobiNetThread_quit;
|
||||
break;
|
||||
case SIGTERM:
|
||||
wait_for_request_quit = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
ssize_t nreads;
|
||||
static UCHAR QMIBuf[4096];
|
||||
PQCQMIMSG pResponse = (PQCQMIMSG)QMIBuf;
|
||||
|
||||
nreads = read(fd, &pResponse->MUXMsg,
|
||||
sizeof(QMIBuf) - sizeof(QCQMI_HDR));
|
||||
if (nreads <= 0) {
|
||||
dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads,
|
||||
errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]);
|
||||
i++) {
|
||||
if (qmiclientId[i] == fd) {
|
||||
pResponse->QMIHdr.QMIType = i;
|
||||
}
|
||||
}
|
||||
|
||||
pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
|
||||
pResponse->QMIHdr.Length =
|
||||
cpu_to_le16(nreads + sizeof(QCQMI_HDR) - 1);
|
||||
pResponse->QMIHdr.CtlFlags = 0x00;
|
||||
pResponse->QMIHdr.ClientId = fd & 0xFF;
|
||||
|
||||
QmiThreadRecvQMI(pResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__GobiNetThread_quit:
|
||||
GobiNetDeInit();
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
QmiThreadRecvQMI(NULL); // main thread may pending on QmiThreadSendQMI()
|
||||
dbg_time("%s exit", __func__);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
static int GobiNetSendQMI(PQCQMIMSG pRequest) { return -1; }
|
||||
static void *GobiNetThread(void *pData)
|
||||
{
|
||||
dbg_time("please set CONFIG_GOBINET");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct qmi_device_ops gobi_qmidev_ops = {
|
||||
.deinit = GobiNetDeInit,
|
||||
.send = GobiNetSendQMI,
|
||||
.read = GobiNetThread,
|
||||
};
|
||||
@@ -1,363 +0,0 @@
|
||||
/*===========================================================================
|
||||
|
||||
M P Q C T L. H
|
||||
DESCRIPTION:
|
||||
|
||||
This module contains QMI QCTL module.
|
||||
|
||||
INITIALIZATION AND SEQUENCING REQUIREMENTS:
|
||||
|
||||
Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved.
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef MPQCTL_H
|
||||
#define MPQCTL_H
|
||||
|
||||
#include "MPQMI.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// ================= QMICTL ==================
|
||||
|
||||
// QMICTL Control Flags
|
||||
#define QMICTL_CTL_FLAG_CMD 0x00
|
||||
#define QMICTL_CTL_FLAG_RSP 0x01
|
||||
#define QMICTL_CTL_FLAG_IND 0x02
|
||||
|
||||
#if 0
|
||||
typedef struct _QMICTL_TRANSACTION_ITEM
|
||||
{
|
||||
LIST_ENTRY List;
|
||||
UCHAR TransactionId; // QMICTL transaction id
|
||||
PVOID Context; // Adapter or IocDev
|
||||
PIRP Irp;
|
||||
} QMICTL_TRANSACTION_ITEM, *PQMICTL_TRANSACTION_ITEM;
|
||||
#endif
|
||||
|
||||
typedef struct _QCQMICTL_MSG_HDR {
|
||||
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType;
|
||||
USHORT Length;
|
||||
} __attribute__((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR;
|
||||
|
||||
#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR)
|
||||
|
||||
typedef struct _QCQMICTL_MSG_HDR_RESP {
|
||||
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType;
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // 0x02 - result code
|
||||
USHORT TLVLength; // 4
|
||||
USHORT QMUXResult; // QMI_RESULT_SUCCESS
|
||||
// QMI_RESULT_FAILURE
|
||||
USHORT QMUXError; // QMI_ERR_INVALID_ARG
|
||||
// QMI_ERR_NO_MEMORY
|
||||
// QMI_ERR_INTERNAL
|
||||
// QMI_ERR_FAULT
|
||||
} __attribute__((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP;
|
||||
|
||||
typedef struct _QCQMICTL_MSG {
|
||||
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType;
|
||||
USHORT Length;
|
||||
UCHAR Payload;
|
||||
} __attribute__((packed)) QCQMICTL_MSG, *PQCQMICTL_MSG;
|
||||
|
||||
// TLV Header
|
||||
typedef struct _QCQMICTL_TLV_HDR {
|
||||
UCHAR TLVType;
|
||||
USHORT TLVLength;
|
||||
} __attribute__((packed)) QCQMICTL_TLV_HDR, *PQCQMICTL_TLV_HDR;
|
||||
|
||||
#define QCQMICTL_TLV_HDR_SIZE sizeof(QCQMICTL_TLV_HDR)
|
||||
|
||||
// QMICTL Type
|
||||
#define QMICTL_SET_INSTANCE_ID_REQ 0x0020
|
||||
#define QMICTL_SET_INSTANCE_ID_RESP 0x0020
|
||||
#define QMICTL_GET_VERSION_REQ 0x0021
|
||||
#define QMICTL_GET_VERSION_RESP 0x0021
|
||||
#define QMICTL_GET_CLIENT_ID_REQ 0x0022
|
||||
#define QMICTL_GET_CLIENT_ID_RESP 0x0022
|
||||
#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023
|
||||
#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023
|
||||
#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024
|
||||
#define QMICTL_INVALID_CLIENT_ID_IND 0x0025
|
||||
#define QMICTL_SET_DATA_FORMAT_REQ 0x0026
|
||||
#define QMICTL_SET_DATA_FORMAT_RESP 0x0026
|
||||
#define QMICTL_SYNC_REQ 0x0027
|
||||
#define QMICTL_SYNC_RESP 0x0027
|
||||
#define QMICTL_SYNC_IND 0x0027
|
||||
|
||||
#define QMICTL_FLAG_REQUEST 0x00
|
||||
#define QMICTL_FLAG_RESPONSE 0x01
|
||||
#define QMICTL_FLAG_INDICATION 0x02
|
||||
|
||||
// QMICTL Message Definitions
|
||||
|
||||
typedef struct _QMICTL_SET_INSTANCE_ID_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_REQ
|
||||
USHORT Length; // 4
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR Value; // Host-unique QMI instance for this device driver
|
||||
} __attribute__((packed)) QMICTL_SET_INSTANCE_ID_REQ_MSG,
|
||||
*PQMICTL_SET_INSTANCE_ID_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_SET_INSTANCE_ID_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult;
|
||||
USHORT QMIError;
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // 0x0002
|
||||
USHORT QMI_ID; // Upper byte is assigned by MSM,
|
||||
// lower assigned by host
|
||||
} __attribute__((packed)) QMICTL_SET_INSTANCE_ID_RESP_MSG,
|
||||
*PQMICTL_SET_INSTANCE_ID_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_GET_VERSION_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_VERSION_REQ
|
||||
USHORT Length; // 0
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // var
|
||||
UCHAR QMUXTypes; // List of one byte QMUX_TYPE values
|
||||
// 0xFF returns a list of versions for all
|
||||
// QMUX_TYPEs implemented on the device
|
||||
} __attribute__((packed)) QMICTL_GET_VERSION_REQ_MSG,
|
||||
*PQMICTL_GET_VERSION_REQ_MSG;
|
||||
|
||||
typedef struct _QMUX_TYPE_VERSION_STRUCT {
|
||||
UCHAR QMUXType;
|
||||
USHORT MajorVersion;
|
||||
USHORT MinorVersion;
|
||||
} __attribute__((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT;
|
||||
|
||||
typedef struct _ADDENDUM_VERSION_PREAMBLE {
|
||||
UCHAR LabelLength;
|
||||
UCHAR Label;
|
||||
} __attribute__((packed)) ADDENDUM_VERSION_PREAMBLE,
|
||||
*PADDENDUM_VERSION_PREAMBLE;
|
||||
|
||||
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_VERSION 0x01
|
||||
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_ADD_VERSION 0x10
|
||||
|
||||
typedef struct _QMICTL_GET_VERSION_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_VERSION_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult;
|
||||
USHORT QMIError;
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // var
|
||||
UCHAR NumElements; // Num of QMUX_TYPE_VERSION_STRUCT
|
||||
QMUX_TYPE_VERSION_STRUCT TypeVersion[0];
|
||||
} __attribute__((packed)) QMICTL_GET_VERSION_RESP_MSG,
|
||||
*PQMICTL_GET_VERSION_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_REQ
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR QMIType; // QMUX type
|
||||
} __attribute__((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG,
|
||||
*PQMICTL_GET_CLIENT_ID_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult; // result code
|
||||
USHORT QMIError; // error code
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // 2
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG,
|
||||
*PQMICTL_GET_CLIENT_ID_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 0x0002
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG,
|
||||
*PQMICTL_RELEASE_CLIENT_ID_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult; // result code
|
||||
USHORT QMIError; // error code
|
||||
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLV2Length; // 2
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG,
|
||||
*PQMICTL_RELEASE_CLIENT_ID_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_REVOKE_CLIENT_ID_IND_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 0x0002
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_REVOKE_CLIENT_ID_IND_MSG,
|
||||
*PQMICTL_REVOKE_CLIENT_ID_IND_MSG;
|
||||
|
||||
typedef struct _QMICTL_INVALID_CLIENT_ID_IND_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 0x0002
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QMICTL_INVALID_CLIENT_ID_IND_MSG,
|
||||
*PQMICTL_INVALID_CLIENT_ID_IND_MSG;
|
||||
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_REQ
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR DataFormat; // 0-default; 1-QoS hdr present
|
||||
} __attribute__((packed)) QMICTL_SET_DATA_FORMAT_REQ_MSG,
|
||||
*PQMICTL_SET_DATA_FORMAT_REQ_MSG;
|
||||
|
||||
#ifdef QC_IP_MODE
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO 0x10
|
||||
#define SET_DATA_FORMAT_LINK_PROTO_ETH 0x0001
|
||||
#define SET_DATA_FORMAT_LINK_PROTO_IP 0x0002
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT {
|
||||
UCHAR TLVType; // Link-Layer Protocol
|
||||
USHORT TLVLength; // 2
|
||||
USHORT LinkProt; // 0x1: ETH; 0x2: IP
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT, *PQMICTL_SET_DATA_FORMAT_TLV_LINK_PROT;
|
||||
|
||||
#ifdef QCMP_UL_TLP
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_UL_TLP 0x11
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_UL_TLP {
|
||||
UCHAR TLVType; // 0x11, Uplink TLP Setting
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR UlTlpSetting; // 0x0: Disable; 0x01: Enable
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_UL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_UL_TLP;
|
||||
#endif // QCMP_UL_TLP
|
||||
|
||||
#ifdef QCMP_DL_TLP
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_DL_TLP 0x13
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_DL_TLP {
|
||||
UCHAR TLVType; // 0x11, Uplink TLP Setting
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR DlTlpSetting; // 0x0: Disable; 0x01: Enable
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_DL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_DL_TLP;
|
||||
#endif // QCMP_DL_TLP
|
||||
|
||||
#endif // QC_IP_MODE
|
||||
|
||||
#ifdef MP_QCQOS_ENABLED
|
||||
#define SET_DATA_FORMAT_TLV_TYPE_QOS_SETTING 0x12
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING {
|
||||
UCHAR TLVType; // 0x12, QoS setting
|
||||
USHORT TLVLength; // 1
|
||||
UCHAR QosSetting; // 0x0: Disable; 0x01: Enable
|
||||
} QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING,
|
||||
*PQMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING;
|
||||
#endif // MP_QCQOS_ENABLED
|
||||
|
||||
typedef struct _QMICTL_SET_DATA_FORMAT_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult; // result code
|
||||
USHORT QMIError; // error code
|
||||
} __attribute__((packed)) QMICTL_SET_DATA_FORMAT_RESP_MSG,
|
||||
*PQMICTL_SET_DATA_FORMAT_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_SYNC_REQ_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_CTL_SYNC_REQ
|
||||
USHORT Length; // 0
|
||||
} __attribute__((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG;
|
||||
|
||||
typedef struct _QMICTL_SYNC_RESP_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_CTL_SYNC_RESP
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||
USHORT TLVLength; // 0x0004
|
||||
USHORT QMIResult;
|
||||
USHORT QMIError;
|
||||
} __attribute__((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG;
|
||||
|
||||
typedef struct _QMICTL_SYNC_IND_MSG {
|
||||
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||
UCHAR TransactionId;
|
||||
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||
USHORT Length;
|
||||
} __attribute__((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG;
|
||||
|
||||
typedef struct _QMICTL_MSG {
|
||||
union {
|
||||
// Message Header
|
||||
QCQMICTL_MSG_HDR QMICTLMsgHdr;
|
||||
QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp;
|
||||
|
||||
// QMICTL Message
|
||||
QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq;
|
||||
QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp;
|
||||
QMICTL_GET_VERSION_REQ_MSG GetVersionReq;
|
||||
QMICTL_GET_VERSION_RESP_MSG GetVersionRsp;
|
||||
QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq;
|
||||
QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp;
|
||||
QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq;
|
||||
QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp;
|
||||
QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd;
|
||||
QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd;
|
||||
QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq;
|
||||
QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp;
|
||||
QMICTL_SYNC_REQ_MSG SyncReq;
|
||||
QMICTL_SYNC_RESP_MSG SyncRsp;
|
||||
QMICTL_SYNC_IND_MSG SyncInd;
|
||||
};
|
||||
} __attribute__((packed)) QMICTL_MSG, *PQMICTL_MSG;
|
||||
|
||||
#endif // MPQCTL_H
|
||||
@@ -1,287 +0,0 @@
|
||||
/*===========================================================================
|
||||
|
||||
M P Q M I. H
|
||||
DESCRIPTION:
|
||||
|
||||
This module contains forward references to the QMI module.
|
||||
|
||||
INITIALIZATION AND SEQUENCING REQUIREMENTS:
|
||||
|
||||
Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved.
|
||||
===========================================================================*/
|
||||
/*===========================================================================
|
||||
|
||||
EDIT HISTORY FOR FILE
|
||||
$Header: //depot/QMI/win/qcdrivers/ndis/MPQMI.h#3 $
|
||||
|
||||
when who what, where, why
|
||||
-------- --- ----------------------------------------------------------
|
||||
11/20/04 hg Initial version.
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef USBQMI_H
|
||||
#define USBQMI_H
|
||||
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned short USHORT;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned int ULONG;
|
||||
typedef unsigned long long ULONG64;
|
||||
typedef char *PCHAR;
|
||||
typedef unsigned char *PUCHAR;
|
||||
typedef int *PINT;
|
||||
typedef int BOOL;
|
||||
|
||||
#define TRUE (1 == 1)
|
||||
#define FALSE (1 != 1)
|
||||
|
||||
#define QMICTL_SUPPORTED_MAJOR_VERSION 1
|
||||
#define QMICTL_SUPPORTED_MINOR_VERSION 0
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// ========= USB Control Message ==========
|
||||
|
||||
#define USB_CTL_MSG_TYPE_QMI 0x01
|
||||
|
||||
// USB Control Message
|
||||
typedef struct _QCUSB_CTL_MSG_HDR {
|
||||
UCHAR IFType;
|
||||
} __attribute__((packed)) QCUSB_CTL_MSG_HDR, *PQCUSB_CTL_MSG_HDR;
|
||||
|
||||
#define QCUSB_CTL_MSG_HDR_SIZE sizeof(QCUSB_CTL_MSG_HDR)
|
||||
|
||||
typedef struct _QCUSB_CTL_MSG {
|
||||
UCHAR IFType;
|
||||
UCHAR Message;
|
||||
} __attribute__((packed)) QCUSB_CTL_MSG, *PQCUSB_CTL_MSG;
|
||||
|
||||
#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01
|
||||
#define QCTLV_TYPE_RESULT_CODE 0x02
|
||||
|
||||
// ================= QMI ==================
|
||||
|
||||
// Define QMI Type
|
||||
typedef enum _QMI_SERVICE_TYPE {
|
||||
QMUX_TYPE_CTL = 0x00,
|
||||
QMUX_TYPE_WDS = 0x01,
|
||||
QMUX_TYPE_DMS = 0x02,
|
||||
QMUX_TYPE_NAS = 0x03,
|
||||
QMUX_TYPE_QOS = 0x04,
|
||||
QMUX_TYPE_WMS = 0x05,
|
||||
QMUX_TYPE_PDS = 0x06,
|
||||
QMUX_TYPE_UIM = 0x0B,
|
||||
QMUX_TYPE_WDS_IPV6 = 0x11,
|
||||
QMUX_TYPE_WDS_ADMIN = 0x1A,
|
||||
QMUX_TYPE_MAX = 0xFF,
|
||||
QMUX_TYPE_ALL = 0xFF
|
||||
} QMI_SERVICE_TYPE;
|
||||
|
||||
typedef enum _QMI_RESULT_CODE_TYPE {
|
||||
QMI_RESULT_SUCCESS = 0x0000,
|
||||
QMI_RESULT_FAILURE = 0x0001
|
||||
} QMI_RESULT_CODE_TYPE;
|
||||
|
||||
typedef enum _QMI_ERROR_CODE_TYPE {
|
||||
QMI_ERR_NONE = 0x0000,
|
||||
QMI_ERR_MALFORMED_MSG = 0x0001,
|
||||
QMI_ERR_NO_MEMORY = 0x0002,
|
||||
QMI_ERR_INTERNAL = 0x0003,
|
||||
QMI_ERR_ABORTED = 0x0004,
|
||||
QMI_ERR_CLIENT_IDS_EXHAUSTED = 0x0005,
|
||||
QMI_ERR_UNABORTABLE_TRANSACTION = 0x0006,
|
||||
QMI_ERR_INVALID_CLIENT_ID = 0x0007,
|
||||
QMI_ERR_NO_THRESHOLDS = 0x0008,
|
||||
QMI_ERR_INVALID_HANDLE = 0x0009,
|
||||
QMI_ERR_INVALID_PROFILE = 0x000A,
|
||||
QMI_ERR_INVALID_PINID = 0x000B,
|
||||
QMI_ERR_INCORRECT_PIN = 0x000C,
|
||||
QMI_ERR_NO_NETWORK_FOUND = 0x000D,
|
||||
QMI_ERR_CALL_FAILED = 0x000E,
|
||||
QMI_ERR_OUT_OF_CALL = 0x000F,
|
||||
QMI_ERR_NOT_PROVISIONED = 0x0010,
|
||||
QMI_ERR_MISSING_ARG = 0x0011,
|
||||
QMI_ERR_ARG_TOO_LONG = 0x0013,
|
||||
QMI_ERR_INVALID_TX_ID = 0x0016,
|
||||
QMI_ERR_DEVICE_IN_USE = 0x0017,
|
||||
QMI_ERR_OP_NETWORK_UNSUPPORTED = 0x0018,
|
||||
QMI_ERR_OP_DEVICE_UNSUPPORTED = 0x0019,
|
||||
QMI_ERR_NO_EFFECT = 0x001A,
|
||||
QMI_ERR_NO_FREE_PROFILE = 0x001B,
|
||||
QMI_ERR_INVALID_PDP_TYPE = 0x001C,
|
||||
QMI_ERR_INVALID_TECH_PREF = 0x001D,
|
||||
QMI_ERR_INVALID_PROFILE_TYPE = 0x001E,
|
||||
QMI_ERR_INVALID_SERVICE_TYPE = 0x001F,
|
||||
QMI_ERR_INVALID_REGISTER_ACTION = 0x0020,
|
||||
QMI_ERR_INVALID_PS_ATTACH_ACTION = 0x0021,
|
||||
QMI_ERR_AUTHENTICATION_FAILED = 0x0022,
|
||||
QMI_ERR_PIN_BLOCKED = 0x0023,
|
||||
QMI_ERR_PIN_PERM_BLOCKED = 0x0024,
|
||||
QMI_ERR_SIM_NOT_INITIALIZED = 0x0025,
|
||||
QMI_ERR_MAX_QOS_REQUESTS_IN_USE = 0x0026,
|
||||
QMI_ERR_INCORRECT_FLOW_FILTER = 0x0027,
|
||||
QMI_ERR_NETWORK_QOS_UNAWARE = 0x0028,
|
||||
QMI_ERR_INVALID_QOS_ID = 0x0029,
|
||||
QMI_ERR_INVALID_ID = 0x0029,
|
||||
QMI_ERR_REQUESTED_NUM_UNSUPPORTED = 0x002A,
|
||||
QMI_ERR_INTERFACE_NOT_FOUND = 0x002B,
|
||||
QMI_ERR_FLOW_SUSPENDED = 0x002C,
|
||||
QMI_ERR_INVALID_DATA_FORMAT = 0x002D,
|
||||
QMI_ERR_GENERAL = 0x002E,
|
||||
QMI_ERR_UNKNOWN = 0x002F,
|
||||
QMI_ERR_INVALID_ARG = 0x0030,
|
||||
QMI_ERR_INVALID_INDEX = 0x0031,
|
||||
QMI_ERR_NO_ENTRY = 0x0032,
|
||||
QMI_ERR_DEVICE_STORAGE_FULL = 0x0033,
|
||||
QMI_ERR_DEVICE_NOT_READY = 0x0034,
|
||||
QMI_ERR_NETWORK_NOT_READY = 0x0035,
|
||||
QMI_ERR_CAUSE_CODE = 0x0036,
|
||||
QMI_ERR_MESSAGE_NOT_SENT = 0x0037,
|
||||
QMI_ERR_MESSAGE_DELIVERY_FAILURE = 0x0038,
|
||||
QMI_ERR_INVALID_MESSAGE_ID = 0x0039,
|
||||
QMI_ERR_ENCODING = 0x003A,
|
||||
QMI_ERR_AUTHENTICATION_LOCK = 0x003B,
|
||||
QMI_ERR_INVALID_TRANSITION = 0x003C,
|
||||
QMI_ERR_NOT_A_MCAST_IFACE = 0x003D,
|
||||
QMI_ERR_MAX_MCAST_REQUESTS_IN_USE = 0x003E,
|
||||
QMI_ERR_INVALID_MCAST_HANDLE = 0x003F,
|
||||
QMI_ERR_INVALID_IP_FAMILY_PREF = 0x0040,
|
||||
QMI_ERR_SESSION_INACTIVE = 0x0041,
|
||||
QMI_ERR_SESSION_INVALID = 0x0042,
|
||||
QMI_ERR_SESSION_OWNERSHIP = 0x0043,
|
||||
QMI_ERR_INSUFFICIENT_RESOURCES = 0x0044,
|
||||
QMI_ERR_DISABLED = 0x0045,
|
||||
QMI_ERR_INVALID_OPERATION = 0x0046,
|
||||
QMI_ERR_INVALID_QMI_CMD = 0x0047,
|
||||
QMI_ERR_TPDU_TYPE = 0x0048,
|
||||
QMI_ERR_SMSC_ADDR = 0x0049,
|
||||
QMI_ERR_INFO_UNAVAILABLE = 0x004A,
|
||||
QMI_ERR_SEGMENT_TOO_LONG = 0x004B,
|
||||
QMI_ERR_SEGMENT_ORDER = 0x004C,
|
||||
QMI_ERR_BUNDLING_NOT_SUPPORTED = 0x004D,
|
||||
QMI_ERR_OP_PARTIAL_FAILURE = 0x004E,
|
||||
QMI_ERR_POLICY_MISMATCH = 0x004F,
|
||||
QMI_ERR_SIM_FILE_NOT_FOUND = 0x0050,
|
||||
QMI_ERR_EXTENDED_INTERNAL = 0x0051,
|
||||
QMI_ERR_ACCESS_DENIED = 0x0052,
|
||||
QMI_ERR_HARDWARE_RESTRICTED = 0x0053,
|
||||
QMI_ERR_ACK_NOT_SENT = 0x0054,
|
||||
QMI_ERR_INJECT_TIMEOUT = 0x0055,
|
||||
QMI_ERR_INCOMPATIBLE_STATE = 0x005A,
|
||||
QMI_ERR_FDN_RESTRICT = 0x005B,
|
||||
QMI_ERR_SUPS_FAILURE_CAUSE = 0x005C,
|
||||
QMI_ERR_NO_RADIO = 0x005D,
|
||||
QMI_ERR_NOT_SUPPORTED = 0x005E,
|
||||
QMI_ERR_NO_SUBSCRIPTION = 0x005F,
|
||||
QMI_ERR_CARD_CALL_CONTROL_FAILED = 0x0060,
|
||||
QMI_ERR_NETWORK_ABORTED = 0x0061,
|
||||
QMI_ERR_MSG_BLOCKED = 0x0062,
|
||||
QMI_ERR_INVALID_SESSION_TYPE = 0x0064,
|
||||
QMI_ERR_INVALID_PB_TYPE = 0x0065,
|
||||
QMI_ERR_NO_SIM = 0x0066,
|
||||
QMI_ERR_PB_NOT_READY = 0x0067,
|
||||
QMI_ERR_PIN_RESTRICTION = 0x0068,
|
||||
QMI_ERR_PIN2_RESTRICTION = 0x0069,
|
||||
QMI_ERR_PUK_RESTRICTION = 0x006A,
|
||||
QMI_ERR_PUK2_RESTRICTION = 0x006B,
|
||||
QMI_ERR_PB_ACCESS_RESTRICTED = 0x006C,
|
||||
QMI_ERR_PB_DELETE_IN_PROG = 0x006D,
|
||||
QMI_ERR_PB_TEXT_TOO_LONG = 0x006E,
|
||||
QMI_ERR_PB_NUMBER_TOO_LONG = 0x006F,
|
||||
QMI_ERR_PB_HIDDEN_KEY_RESTRICTION = 0x0070
|
||||
} QMI_ERROR_CODE_TYPE;
|
||||
|
||||
#define QCQMI_CTL_FLAG_SERVICE 0x80
|
||||
#define QCQMI_CTL_FLAG_CTL_POINT 0x00
|
||||
|
||||
typedef struct _QCQMI_HDR {
|
||||
UCHAR IFType;
|
||||
USHORT Length;
|
||||
UCHAR CtlFlags; // reserved
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
} __attribute__((packed)) QCQMI_HDR, *PQCQMI_HDR;
|
||||
|
||||
#define QCQMI_HDR_SIZE (sizeof(QCQMI_HDR) - 1)
|
||||
|
||||
typedef struct _QCQMI {
|
||||
UCHAR IFType;
|
||||
USHORT Length;
|
||||
UCHAR CtlFlags; // reserved
|
||||
UCHAR QMIType;
|
||||
UCHAR ClientId;
|
||||
UCHAR SDU;
|
||||
} __attribute__((packed)) QCQMI, *PQCQMI;
|
||||
|
||||
typedef struct _QMI_SERVICE_VERSION {
|
||||
USHORT Major;
|
||||
USHORT Minor;
|
||||
USHORT AddendumMajor;
|
||||
USHORT AddendumMinor;
|
||||
} __attribute__((packed)) QMI_SERVICE_VERSION, *PQMI_SERVICE_VERSION;
|
||||
|
||||
// ================= QMUX ==================
|
||||
|
||||
#define QMUX_MSG_OVERHEAD_BYTES 4 // Type(USHORT) Length(USHORT) -- header
|
||||
|
||||
#define QMUX_BROADCAST_CID 0xFF
|
||||
|
||||
typedef struct _QCQMUX_HDR {
|
||||
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
|
||||
USHORT TransactionId;
|
||||
} __attribute__((packed)) QCQMUX_HDR, *PQCQMUX_HDR;
|
||||
|
||||
typedef struct _QCQMUX {
|
||||
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
|
||||
USHORT TransactionId;
|
||||
UCHAR Message; // Type(2), Length(2), Value
|
||||
} __attribute__((packed)) QCQMUX, *PQCQMUX;
|
||||
|
||||
#define QCQMUX_HDR_SIZE sizeof(QCQMUX_HDR)
|
||||
|
||||
typedef struct _QCQMUX_MSG_HDR {
|
||||
USHORT Type;
|
||||
USHORT Length;
|
||||
} __attribute__((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR;
|
||||
|
||||
#define QCQMUX_MSG_HDR_SIZE sizeof(QCQMUX_MSG_HDR)
|
||||
|
||||
typedef struct _QCQMUX_MSG_HDR_RESP {
|
||||
USHORT Type;
|
||||
USHORT Length;
|
||||
UCHAR TLVType; // 0x02 - result code
|
||||
USHORT TLVLength; // 4
|
||||
USHORT QMUXResult; // QMI_RESULT_SUCCESS
|
||||
// QMI_RESULT_FAILURE
|
||||
USHORT QMUXError; // QMI_ERR_INVALID_ARG
|
||||
// QMI_ERR_NO_MEMORY
|
||||
// QMI_ERR_INTERNAL
|
||||
// QMI_ERR_FAULT
|
||||
} __attribute__((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP;
|
||||
|
||||
typedef struct _QCQMUX_TLV {
|
||||
UCHAR Type;
|
||||
USHORT Length;
|
||||
UCHAR Value;
|
||||
} __attribute__((packed)) QCQMUX_TLV, *PQCQMUX_TLV;
|
||||
|
||||
typedef struct _QMI_TLV_HDR {
|
||||
UCHAR TLVType;
|
||||
USHORT TLVLength;
|
||||
} __attribute__((packed)) QMI_TLV_HDR, *PQMI_TLV_HDR;
|
||||
|
||||
// QMUX Message Definitions -- QMI SDU
|
||||
#define QMUX_CTL_FLAG_SINGLE_MSG 0x00
|
||||
#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01
|
||||
#define QMUX_CTL_FLAG_TYPE_CMD 0x00
|
||||
#define QMUX_CTL_FLAG_TYPE_RSP 0x02
|
||||
#define QMUX_CTL_FLAG_TYPE_IND 0x04
|
||||
#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01
|
||||
#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // USBQMI_H
|
||||
@@ -1,437 +0,0 @@
|
||||
#include "QMIThread.h"
|
||||
static char line[1024];
|
||||
static pthread_mutex_t dumpQMIMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#undef dbg
|
||||
#define dbg(format, arg...) \
|
||||
do { \
|
||||
if (strlen(line) < sizeof(line)) \
|
||||
snprintf(&line[strlen(line)], sizeof(line) - strlen(line), format, \
|
||||
##arg); \
|
||||
} while (0)
|
||||
|
||||
PQMI_TLV_HDR GetTLV(PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType);
|
||||
|
||||
typedef struct {
|
||||
UINT type;
|
||||
const char *name;
|
||||
} QMI_NAME_T;
|
||||
|
||||
#define qmi_name_item(type) \
|
||||
{ \
|
||||
type, #type \
|
||||
}
|
||||
|
||||
static const QMI_NAME_T qmux_ctl_QMICTLType[] = {
|
||||
// QMICTL Type
|
||||
qmi_name_item(QMICTL_SET_INSTANCE_ID_REQ), // 0x0020
|
||||
qmi_name_item(QMICTL_SET_INSTANCE_ID_RESP), // 0x0020
|
||||
qmi_name_item(QMICTL_GET_VERSION_REQ), // 0x0021
|
||||
qmi_name_item(QMICTL_GET_VERSION_RESP), // 0x0021
|
||||
qmi_name_item(QMICTL_GET_CLIENT_ID_REQ), // 0x0022
|
||||
qmi_name_item(QMICTL_GET_CLIENT_ID_RESP), // 0x0022
|
||||
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_REQ), // 0x0023
|
||||
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_RESP), // 0x0023
|
||||
qmi_name_item(QMICTL_REVOKE_CLIENT_ID_IND), // 0x0024
|
||||
qmi_name_item(QMICTL_INVALID_CLIENT_ID_IND), // 0x0025
|
||||
qmi_name_item(QMICTL_SET_DATA_FORMAT_REQ), // 0x0026
|
||||
qmi_name_item(QMICTL_SET_DATA_FORMAT_RESP), // 0x0026
|
||||
qmi_name_item(QMICTL_SYNC_REQ), // 0x0027
|
||||
qmi_name_item(QMICTL_SYNC_RESP), // 0x0027
|
||||
qmi_name_item(QMICTL_SYNC_IND), // 0x0027
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_CtlFlags[] = {
|
||||
qmi_name_item(QMUX_CTL_FLAG_TYPE_CMD),
|
||||
qmi_name_item(QMUX_CTL_FLAG_TYPE_RSP),
|
||||
qmi_name_item(QMUX_CTL_FLAG_TYPE_IND),
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_wds_Type[] = {
|
||||
qmi_name_item(QMIWDS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||
qmi_name_item(QMIWDS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||
qmi_name_item(QMIWDS_EVENT_REPORT_IND), // 0x0001
|
||||
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_REQ), // 0x0020
|
||||
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_RESP), // 0x0020
|
||||
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_REQ), // 0x0021
|
||||
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_RESP), // 0x0021
|
||||
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_REQ), // 0x0022
|
||||
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_RESP), // 0x0022
|
||||
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_IND), // 0x0022
|
||||
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ), // 0x0023
|
||||
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP), // 0x0023
|
||||
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_REQ), // 0x0024
|
||||
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_RESP), // 0x0024
|
||||
//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610
|
||||
qmi_name_item(QMIWDS_CREATE_PROFILE_SETTINGS_REQ), // 0x0027
|
||||
qmi_name_item(QMIWDS_CREATE_PROFILE_SETTINGS_RESP), // 0x0027
|
||||
//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610
|
||||
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ), // 0x0028
|
||||
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_RESP), // 0x0028
|
||||
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_REQ), // 0x002B
|
||||
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_RESP), // 0x002BD
|
||||
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_REQ), // 0x002C
|
||||
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_RESP), // 0x002C
|
||||
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_REQ), // 0x002D
|
||||
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_RESP), // 0x002D
|
||||
qmi_name_item(QMIWDS_GET_MIP_MODE_REQ), // 0x002F
|
||||
qmi_name_item(QMIWDS_GET_MIP_MODE_RESP), // 0x002F
|
||||
qmi_name_item(QMIWDS_GET_DATA_BEARER_REQ), // 0x0037
|
||||
qmi_name_item(QMIWDS_GET_DATA_BEARER_RESP), // 0x0037
|
||||
qmi_name_item(QMIWDS_DUN_CALL_INFO_REQ), // 0x0038
|
||||
qmi_name_item(QMIWDS_DUN_CALL_INFO_RESP), // 0x0038
|
||||
qmi_name_item(QMIWDS_DUN_CALL_INFO_IND), // 0x0038
|
||||
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ), // 0x004D
|
||||
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP), // 0x004D
|
||||
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_REQ), // 0x0051
|
||||
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_RESP), // 0x0051
|
||||
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_REQ), // 0x00A2
|
||||
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_RESP), // 0x00A2
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_dms_Type[] = {
|
||||
// ======================= DMS ==============================
|
||||
qmi_name_item(QMIDMS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||
qmi_name_item(QMIDMS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||
qmi_name_item(QMIDMS_EVENT_REPORT_IND), // 0x0001
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_CAP_REQ), // 0x0020
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_CAP_RESP), // 0x0020
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MFR_REQ), // 0x0021
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MFR_RESP), // 0x0021
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_REQ), // 0x0022
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_RESP), // 0x0022
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_REQ), // 0x0023
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_RESP), // 0x0023
|
||||
qmi_name_item(QMIDMS_GET_MSISDN_REQ), // 0x0024
|
||||
qmi_name_item(QMIDMS_GET_MSISDN_RESP), // 0x0024
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ), // 0x0025
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP), // 0x0025
|
||||
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_REQ), // 0x0027
|
||||
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_RESP), // 0x0027
|
||||
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_REQ), // 0x0028
|
||||
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_RESP), // 0x0028
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_REQ), // 0x0029
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_RESP), // 0x0029
|
||||
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_REQ), // 0x002A
|
||||
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_RESP), // 0x002A
|
||||
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_REQ), // 0x002B
|
||||
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_RESP), // 0x002B
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_REQ), // 0x002C
|
||||
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_RESP), // 0x002C
|
||||
qmi_name_item(QMIDMS_GET_OPERATING_MODE_REQ), // 0x002D
|
||||
qmi_name_item(QMIDMS_GET_OPERATING_MODE_RESP), // 0x002D
|
||||
qmi_name_item(QMIDMS_SET_OPERATING_MODE_REQ), // 0x002E
|
||||
qmi_name_item(QMIDMS_SET_OPERATING_MODE_RESP), // 0x002E
|
||||
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_REQ), // 0x0031
|
||||
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_RESP), // 0x0031
|
||||
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_REQ), // 0x0032
|
||||
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_RESP), // 0x0032
|
||||
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_REQ), // 0x0033
|
||||
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_RESP), // 0x0033
|
||||
qmi_name_item(QMIDMS_UIM_GET_ICCID_REQ), // 0x003C
|
||||
qmi_name_item(QMIDMS_UIM_GET_ICCID_RESP), // 0x003C
|
||||
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_REQ), // 0x0040
|
||||
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_RESP), // 0x0040
|
||||
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_REQ), // 0x0041
|
||||
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_RESP), // 0x0041
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_REQ), // 0x0042
|
||||
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_RESP), // 0x0042
|
||||
qmi_name_item(QMIDMS_UIM_GET_IMSI_REQ), // 0x0043
|
||||
qmi_name_item(QMIDMS_UIM_GET_IMSI_RESP), // 0x0043
|
||||
qmi_name_item(QMIDMS_UIM_GET_STATE_REQ), // 0x0044
|
||||
qmi_name_item(QMIDMS_UIM_GET_STATE_RESP), // 0x0044
|
||||
qmi_name_item(QMIDMS_GET_BAND_CAP_REQ), // 0x0045
|
||||
qmi_name_item(QMIDMS_GET_BAND_CAP_RESP), // 0x0045
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_nas_Type[] = {
|
||||
// ======================= NAS ==============================
|
||||
qmi_name_item(QMINAS_SET_EVENT_REPORT_REQ), // 0x0002
|
||||
qmi_name_item(QMINAS_SET_EVENT_REPORT_RESP), // 0x0002
|
||||
qmi_name_item(QMINAS_EVENT_REPORT_IND), // 0x0002
|
||||
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_REQ), // 0x0020
|
||||
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_RESP), // 0x0020
|
||||
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_REQ), // 0x0021
|
||||
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_RESP), // 0x0021
|
||||
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_REQ), // 0x0022
|
||||
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_RESP), // 0x0022
|
||||
qmi_name_item(QMINAS_INITIATE_ATTACH_REQ), // 0x0023
|
||||
qmi_name_item(QMINAS_INITIATE_ATTACH_RESP), // 0x0023
|
||||
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_REQ), // 0x0024
|
||||
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_RESP), // 0x0024
|
||||
qmi_name_item(QMINAS_SERVING_SYSTEM_IND), // 0x0024
|
||||
qmi_name_item(QMINAS_GET_HOME_NETWORK_REQ), // 0x0025
|
||||
qmi_name_item(QMINAS_GET_HOME_NETWORK_RESP), // 0x0025
|
||||
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_REQ), // 0x0026
|
||||
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_RESP), // 0x0026
|
||||
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_REQ), // 0x0027
|
||||
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_RESP), // 0x0027
|
||||
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_REQ), // 0x0028
|
||||
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_RESP), // 0x0028
|
||||
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_REQ), // 0x0029
|
||||
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_RESP), // 0x0029
|
||||
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_REQ), // 0x002A
|
||||
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_RESP), // 0x002A
|
||||
qmi_name_item(QMINAS_GET_RF_BAND_INFO_REQ), // 0x0031
|
||||
qmi_name_item(QMINAS_GET_RF_BAND_INFO_RESP), // 0x0031
|
||||
qmi_name_item(QMINAS_GET_PLMN_NAME_REQ), // 0x0044
|
||||
qmi_name_item(QMINAS_GET_PLMN_NAME_RESP), // 0x0044
|
||||
qmi_name_item(FIBO_PACKET_TRANSFER_START_IND), // 0X100
|
||||
qmi_name_item(FIBO_PACKET_TRANSFER_END_IND), // 0X101
|
||||
qmi_name_item(QMINAS_GET_SYS_INFO_REQ), // 0x004D
|
||||
qmi_name_item(QMINAS_GET_SYS_INFO_RESP), // 0x004D
|
||||
qmi_name_item(QMINAS_SYS_INFO_IND), // 0x004D
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_wms_Type[] = {
|
||||
// ======================= WMS ==============================
|
||||
qmi_name_item(QMIWMS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||
qmi_name_item(QMIWMS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||
qmi_name_item(QMIWMS_EVENT_REPORT_IND), // 0x0001
|
||||
qmi_name_item(QMIWMS_RAW_SEND_REQ), // 0x0020
|
||||
qmi_name_item(QMIWMS_RAW_SEND_RESP), // 0x0020
|
||||
qmi_name_item(QMIWMS_RAW_WRITE_REQ), // 0x0021
|
||||
qmi_name_item(QMIWMS_RAW_WRITE_RESP), // 0x0021
|
||||
qmi_name_item(QMIWMS_RAW_READ_REQ), // 0x0022
|
||||
qmi_name_item(QMIWMS_RAW_READ_RESP), // 0x0022
|
||||
qmi_name_item(QMIWMS_MODIFY_TAG_REQ), // 0x0023
|
||||
qmi_name_item(QMIWMS_MODIFY_TAG_RESP), // 0x0023
|
||||
qmi_name_item(QMIWMS_DELETE_REQ), // 0x0024
|
||||
qmi_name_item(QMIWMS_DELETE_RESP), // 0x0024
|
||||
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_REQ), // 0x0030
|
||||
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_RESP), // 0x0030
|
||||
qmi_name_item(QMIWMS_LIST_MESSAGES_REQ), // 0x0031
|
||||
qmi_name_item(QMIWMS_LIST_MESSAGES_RESP), // 0x0031
|
||||
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_REQ), // 0x0034
|
||||
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_RESP), // 0x0034
|
||||
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_REQ), // 0x0035
|
||||
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_RESP), // 0x0035
|
||||
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_REQ), // 0x0036
|
||||
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_RESP), // 0x0036
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_wds_admin_Type[] = {
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ), // 0x0020
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_RESP), // 0x0020
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_REQ), // 0x0021
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_RESP), // 0x0021
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ), // 0x002B
|
||||
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP), // 0x002B
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ), // 0x002C
|
||||
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP), // 0x002C
|
||||
};
|
||||
|
||||
static const QMI_NAME_T qmux_uim_Type[] = {
|
||||
qmi_name_item(QMIUIM_READ_TRANSPARENT_REQ), // 0x0020
|
||||
qmi_name_item(QMIUIM_READ_TRANSPARENT_RESP), // 0x0020
|
||||
qmi_name_item(QMIUIM_READ_TRANSPARENT_IND), // 0x0020
|
||||
qmi_name_item(QMIUIM_READ_RECORD_REQ), // 0x0021
|
||||
qmi_name_item(QMIUIM_READ_RECORD_RESP), // 0x0021
|
||||
qmi_name_item(QMIUIM_READ_RECORD_IND), // 0x0021
|
||||
qmi_name_item(QMIUIM_WRITE_TRANSPARENT_REQ), // 0x0022
|
||||
qmi_name_item(QMIUIM_WRITE_TRANSPARENT_RESP), // 0x0022
|
||||
qmi_name_item(QMIUIM_WRITE_TRANSPARENT_IND), // 0x0022
|
||||
qmi_name_item(QMIUIM_WRITE_RECORD_REQ), // 0x0023
|
||||
qmi_name_item(QMIUIM_WRITE_RECORD_RESP), // 0x0023
|
||||
qmi_name_item(QMIUIM_WRITE_RECORD_IND), // 0x0023
|
||||
qmi_name_item(QMIUIM_SET_PIN_PROTECTION_REQ), // 0x0025
|
||||
qmi_name_item(QMIUIM_SET_PIN_PROTECTION_RESP), // 0x0025
|
||||
qmi_name_item(QMIUIM_SET_PIN_PROTECTION_IND), // 0x0025
|
||||
qmi_name_item(QMIUIM_VERIFY_PIN_REQ), // 0x0026
|
||||
qmi_name_item(QMIUIM_VERIFY_PIN_RESP), // 0x0026
|
||||
qmi_name_item(QMIUIM_VERIFY_PIN_IND), // 0x0026
|
||||
qmi_name_item(QMIUIM_UNBLOCK_PIN_REQ), // 0x0027
|
||||
qmi_name_item(QMIUIM_UNBLOCK_PIN_RESP), // 0x0027
|
||||
qmi_name_item(QMIUIM_UNBLOCK_PIN_IND), // 0x0027
|
||||
qmi_name_item(QMIUIM_CHANGE_PIN_REQ), // 0x0028
|
||||
qmi_name_item(QMIUIM_CHANGE_PIN_RESP), // 0x0028
|
||||
qmi_name_item(QMIUIM_CHANGE_PIN_IND), // 0x0028
|
||||
qmi_name_item(QMIUIM_DEPERSONALIZATION_REQ), // 0x0029
|
||||
qmi_name_item(QMIUIM_DEPERSONALIZATION_RESP), // 0x0029
|
||||
qmi_name_item(QMIUIM_EVENT_REG_REQ), // 0x002E
|
||||
qmi_name_item(QMIUIM_EVENT_REG_RESP), // 0x002E
|
||||
qmi_name_item(QMIUIM_GET_CARD_STATUS_REQ), // 0x002F
|
||||
qmi_name_item(QMIUIM_GET_CARD_STATUS_RESP), // 0x002F
|
||||
qmi_name_item(QMIUIM_STATUS_CHANGE_IND), // 0x0032
|
||||
};
|
||||
|
||||
static const char *qmi_name_get(const QMI_NAME_T *table, size_t size, int type,
|
||||
const char *tag)
|
||||
{
|
||||
static char unknow[40];
|
||||
size_t i;
|
||||
|
||||
if (qmux_CtlFlags == table) {
|
||||
if (!strcmp(tag, "_REQ"))
|
||||
tag = "_CMD";
|
||||
else if (!strcmp(tag, "_RESP"))
|
||||
tag = "_RSP";
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (table[i].type == (UINT)type) {
|
||||
if (!tag || (strstr(table[i].name, tag)))
|
||||
return table[i].name;
|
||||
}
|
||||
}
|
||||
sprintf(unknow, "unknow_%x", type);
|
||||
return unknow;
|
||||
}
|
||||
|
||||
#define QMI_NAME(table, type) \
|
||||
qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, 0)
|
||||
#define QMUX_NAME(table, type, tag) \
|
||||
qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, tag)
|
||||
|
||||
void dump_tlv(PQCQMUX_MSG_HDR pQMUXMsgHdr)
|
||||
{
|
||||
int TLVFind = 0;
|
||||
int i;
|
||||
// dbg("QCQMUX_TLV-----------------------------------\n");
|
||||
// dbg("{Type,\tLength,\tValue}\n");
|
||||
|
||||
while (1) {
|
||||
PQMI_TLV_HDR TLVHdr = GetTLV(pQMUXMsgHdr, 0x1000 + (++TLVFind));
|
||||
if (TLVHdr == NULL)
|
||||
break;
|
||||
|
||||
// if ((TLVHdr->TLVType == 0x02) && ((USHORT *)(TLVHdr+1))[0])
|
||||
{
|
||||
dbg("{%02x,\t%04x,\t", TLVHdr->TLVType,
|
||||
le16_to_cpu(TLVHdr->TLVLength));
|
||||
for (i = 0; i < le16_to_cpu(TLVHdr->TLVLength); i++) {
|
||||
dbg("%02x ", ((UCHAR *)(TLVHdr + 1))[i]);
|
||||
}
|
||||
dbg("}\n");
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
void dump_ctl(PQCQMICTL_MSG_HDR CTLHdr)
|
||||
{
|
||||
const char *tag;
|
||||
|
||||
// dbg("QCQMICTL_MSG--------------------------------------------\n");
|
||||
// dbg("CtlFlags: %02x\t\t%s\n", CTLHdr->CtlFlags,
|
||||
// QMI_NAME(qmi_ctl_CtlFlags, CTLHdr->CtlFlags));
|
||||
dbg("TransactionId: %02x\n", CTLHdr->TransactionId);
|
||||
switch (CTLHdr->CtlFlags) {
|
||||
case QMICTL_FLAG_REQUEST:
|
||||
tag = "_REQ";
|
||||
break;
|
||||
case QMICTL_FLAG_RESPONSE:
|
||||
tag = "_RESP";
|
||||
break;
|
||||
case QMICTL_FLAG_INDICATION:
|
||||
tag = "_IND";
|
||||
break;
|
||||
default:
|
||||
tag = 0;
|
||||
break;
|
||||
}
|
||||
dbg("QMICTLType: %04x\t%s\n", le16_to_cpu(CTLHdr->QMICTLType),
|
||||
QMUX_NAME(qmux_ctl_QMICTLType, le16_to_cpu(CTLHdr->QMICTLType), tag));
|
||||
dbg("Length: %04x\n", le16_to_cpu(CTLHdr->Length));
|
||||
|
||||
dump_tlv((PQCQMUX_MSG_HDR)(&CTLHdr->QMICTLType));
|
||||
}
|
||||
|
||||
int dump_qmux(QMI_SERVICE_TYPE serviceType, PQCQMUX_HDR QMUXHdr)
|
||||
{
|
||||
PQCQMUX_MSG_HDR QMUXMsgHdr = (PQCQMUX_MSG_HDR)(QMUXHdr + 1);
|
||||
CHAR *tag;
|
||||
|
||||
// dbg("QCQMUX--------------------------------------------\n");
|
||||
switch (QMUXHdr->CtlFlags & QMUX_CTL_FLAG_MASK_TYPE) {
|
||||
case QMUX_CTL_FLAG_TYPE_CMD:
|
||||
tag = "_REQ";
|
||||
break;
|
||||
case QMUX_CTL_FLAG_TYPE_RSP:
|
||||
tag = "_RESP";
|
||||
break;
|
||||
case QMUX_CTL_FLAG_TYPE_IND:
|
||||
tag = "_IND";
|
||||
break;
|
||||
default:
|
||||
tag = 0;
|
||||
break;
|
||||
}
|
||||
// dbg("CtlFlags: %02x\t\t%s\n", QMUXHdr->CtlFlags,
|
||||
// QMUX_NAME(qmux_CtlFlags, QMUXHdr->CtlFlags, tag));
|
||||
dbg("TransactionId: %04x\n", le16_to_cpu(QMUXHdr->TransactionId));
|
||||
|
||||
// dbg("QCQMUX_MSG_HDR-----------------------------------\n");
|
||||
switch (serviceType) {
|
||||
case QMUX_TYPE_DMS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_dms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_NAS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_nas_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_WDS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_wds_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_WMS:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_wms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_WDS_ADMIN:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_wds_admin_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_UIM:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
QMUX_NAME(qmux_uim_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||
break;
|
||||
case QMUX_TYPE_PDS:
|
||||
case QMUX_TYPE_QOS:
|
||||
case QMUX_TYPE_CTL:
|
||||
default:
|
||||
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||
"PDS/QOS/CTL/unknown!");
|
||||
break;
|
||||
}
|
||||
dbg("Length: %04x\n", le16_to_cpu(QMUXMsgHdr->Length));
|
||||
|
||||
dump_tlv(QMUXMsgHdr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_qmi(void *dataBuffer, int dataLen)
|
||||
{
|
||||
PQCQMI_HDR QMIHdr = (PQCQMI_HDR)dataBuffer;
|
||||
PQCQMUX_HDR QMUXHdr = (PQCQMUX_HDR)(QMIHdr + 1);
|
||||
PQCQMICTL_MSG_HDR CTLHdr = (PQCQMICTL_MSG_HDR)(QMIHdr + 1);
|
||||
|
||||
int i;
|
||||
|
||||
if (!debug_qmi)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&dumpQMIMutex);
|
||||
line[0] = 0;
|
||||
for (i = 0; i < dataLen; i++) {
|
||||
dbg("%02x ", ((unsigned char *)dataBuffer)[i]);
|
||||
}
|
||||
dbg_time("%s", line);
|
||||
line[0] = 0;
|
||||
|
||||
// dbg("QCQMI_HDR-----------------------------------------");
|
||||
// dbg("IFType: %02x\t\t%s", QMIHdr->IFType,
|
||||
// QMI_NAME(qmi_IFType, QMIHdr->IFType)); dbg("Length: %04x",
|
||||
// le16_to_cpu(QMIHdr->Length)); dbg("CtlFlags: %02x\t\t%s",
|
||||
// QMIHdr->CtlFlags, QMI_NAME(qmi_CtlFlags, QMIHdr->CtlFlags));
|
||||
// dbg("QMIType: %02x\t\t%s", QMIHdr->QMIType, QMI_NAME(qmi_QMIType,
|
||||
// QMIHdr->QMIType)); dbg("ClientId: %02x", QMIHdr->ClientId);
|
||||
|
||||
if (QMIHdr->QMIType == QMUX_TYPE_CTL) {
|
||||
dump_ctl(CTLHdr);
|
||||
} else {
|
||||
dump_qmux(QMIHdr->QMIType, QMUXHdr);
|
||||
}
|
||||
dbg_time("%s", line);
|
||||
pthread_mutex_unlock(&dumpQMIMutex);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,42 +0,0 @@
|
||||
ifneq ($(CROSS_COMPILE),)
|
||||
CROSS-COMPILE:=$(CROSS_COMPILE)
|
||||
endif
|
||||
|
||||
CFLAGS += -DGHT_FEATURE_PCIE_AUTO
|
||||
|
||||
ifeq ($(CC),cc)
|
||||
CC:=$(CROSS-COMPILE)gcc
|
||||
endif
|
||||
LD:=$(CROSS-COMPILE)ld
|
||||
|
||||
SRC=QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c query_pcie_mode.c
|
||||
|
||||
FB_DHCP=udhcpc.c
|
||||
|
||||
FIBO_PROXY_SRC=fibo_qmimsg_server.c
|
||||
|
||||
LIBMNL=libmnl/ifutils.c libmnl/attr.c libmnl/callback.c libmnl/nlmsg.c libmnl/socket.c
|
||||
FB_NDHCP=udhcpc_netlink.c
|
||||
FB_NDHCP+=${LIBMNL}
|
||||
|
||||
release: clean
|
||||
$(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_NDHCP} -o fibocom-dial -lpthread -ldl
|
||||
$(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.c util.c -o multi-pdn-manager -lpthread -ldl
|
||||
$(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl
|
||||
|
||||
dhcp: clean
|
||||
$(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_DHCP} -o fibocom-dial -lpthread -ldl
|
||||
$(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.c util.c -o multi-pdn-manager -lpthread -ldl
|
||||
$(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl
|
||||
|
||||
ndhcp: clean
|
||||
$(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_NDHCP} -o fibocom-dial -lpthread -ldl
|
||||
$(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.cutil.c -o multi-pdn-manager -lpthread -ldl
|
||||
$(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl
|
||||
|
||||
qmi-proxy:
|
||||
$(CC) -Wall -s fibo-qmi-proxy.c -o fibo-qmi-proxy -lpthread -ldl
|
||||
|
||||
clean:
|
||||
rm -rf fibocom-dial *~ multi-pdn-manager fibo_qmimsg_server
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,260 +0,0 @@
|
||||
#ifndef __QMI_THREAD_H__
|
||||
#define __QMI_THREAD_H__
|
||||
|
||||
#define CONFIG_GOBINET
|
||||
#define CONFIG_QMIWWAN
|
||||
#define CONFIG_SIM
|
||||
#define CONFIG_APN
|
||||
#define CONFIG_VERSION
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
#define CONFIG_IMSI_ICCID
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
#define CONFIG_DEFAULT_PDP 1
|
||||
#define CONFIG_DEFAULT_PDPINDEX 1
|
||||
//#define CONFIG_IMSI_ICCID
|
||||
|
||||
#define CONFIG_RESET_RADIO \
|
||||
(45) // Reset Radiao(AT+CFUN=4,AT+CFUN=1) when cann not register network or
|
||||
// setup data call in 45 seconds
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "MPQCTL.h"
|
||||
#include "MPQMI.h"
|
||||
#include "MPQMUX.h"
|
||||
|
||||
#define DEVICE_CLASS_UNKNOWN 0
|
||||
#define DEVICE_CLASS_CDMA 1
|
||||
#define DEVICE_CLASS_GSM 2
|
||||
|
||||
#define WWAN_DATA_CLASS_NONE 0x00000000
|
||||
#define WWAN_DATA_CLASS_GPRS 0x00000001
|
||||
#define WWAN_DATA_CLASS_EDGE 0x00000002 /* EGPRS */
|
||||
#define WWAN_DATA_CLASS_UMTS 0x00000004
|
||||
#define WWAN_DATA_CLASS_HSDPA 0x00000008
|
||||
#define WWAN_DATA_CLASS_HSUPA 0x00000010
|
||||
#define WWAN_DATA_CLASS_LTE 0x00000020
|
||||
//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605
|
||||
#define WWAN_DATA_CLASS_5G 0x00000040
|
||||
//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605
|
||||
#define WWAN_DATA_CLASS_1XRTT 0x00010000
|
||||
#define WWAN_DATA_CLASS_1XEVDO 0x00020000
|
||||
#define WWAN_DATA_CLASS_1XEVDO_REVA 0x00040000
|
||||
#define WWAN_DATA_CLASS_1XEVDV 0x00080000
|
||||
#define WWAN_DATA_CLASS_3XRTT 0x00100000
|
||||
#define WWAN_DATA_CLASS_1XEVDO_REVB 0x00200000 /* for future use */
|
||||
#define WWAN_DATA_CLASS_UMB 0x00400000
|
||||
#define WWAN_DATA_CLASS_CUSTOM 0x80000000
|
||||
|
||||
struct wwan_data_class_str {
|
||||
ULONG class;
|
||||
CHAR *str;
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct _QCQMIMSG {
|
||||
QCQMI_HDR QMIHdr;
|
||||
union {
|
||||
QMICTL_MSG CTLMsg;
|
||||
QMUX_MSG MUXMsg;
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
QMUX_MSG QMUXMsgHdrResp;
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
};
|
||||
} __attribute__((packed)) QCQMIMSG, *PQCQMIMSG;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct __IPV4 {
|
||||
uint32_t Address;
|
||||
uint32_t Gateway;
|
||||
uint32_t SubnetMask;
|
||||
uint32_t DnsPrimary;
|
||||
uint32_t DnsSecondary;
|
||||
uint32_t Mtu;
|
||||
} IPV4_T;
|
||||
|
||||
typedef struct __IPV6 {
|
||||
UCHAR Address[16];
|
||||
UCHAR Gateway[16];
|
||||
UCHAR SubnetMask[16];
|
||||
UCHAR DnsPrimary[16];
|
||||
UCHAR DnsSecondary[16];
|
||||
UCHAR PrefixLengthIPAddr;
|
||||
UCHAR PrefixLengthGateway;
|
||||
ULONG Mtu;
|
||||
} IPV6_T;
|
||||
|
||||
#define IpFamilyV4 (0x04)
|
||||
#define IpFamilyV6 (0x06)
|
||||
|
||||
struct __PROFILE;
|
||||
struct qmi_device_ops {
|
||||
int (*init)(struct __PROFILE *profile);
|
||||
int (*deinit)(void);
|
||||
int (*send)(PQCQMIMSG pRequest);
|
||||
void *(*read)(void *pData);
|
||||
};
|
||||
extern int (*qmidev_send)(PQCQMIMSG pRequest);
|
||||
|
||||
#ifndef bool
|
||||
#define bool uint8_t
|
||||
#endif
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
typedef struct {
|
||||
unsigned int size;
|
||||
unsigned int rx_urb_size;
|
||||
unsigned int ep_type;
|
||||
unsigned int iface_id;
|
||||
unsigned int qmap_mode;
|
||||
unsigned int qmap_version;
|
||||
unsigned int dl_minimum_padding;
|
||||
char ifname[8][16];
|
||||
unsigned char mux_id[8];
|
||||
} RMNET_INFO;
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
|
||||
typedef struct __PROFILE {
|
||||
char *qmichannel;
|
||||
char *usbnet_adapter;
|
||||
char *qmapnet_adapter;
|
||||
const char *driver_name;
|
||||
int qmap_mode;
|
||||
int qmap_size;
|
||||
int qmap_version;
|
||||
const char *apn;
|
||||
const char *user;
|
||||
const char *password;
|
||||
const char *pincode;
|
||||
int auth;
|
||||
int pdp;
|
||||
int pdpindex;
|
||||
int pdpnum;
|
||||
int curIpFamily;
|
||||
int rawIP;
|
||||
int muxid;
|
||||
IPV4_T ipv4;
|
||||
IPV6_T ipv6;
|
||||
int ipv4_flag;
|
||||
int ipv6_flag;
|
||||
|
||||
//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001
|
||||
int ipv6_prigateway_flag;
|
||||
//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001
|
||||
|
||||
int dual_flag;
|
||||
int apntype;
|
||||
const struct qmi_device_ops *qmi_ops;
|
||||
bool loopback_state;
|
||||
int replication_factor;
|
||||
//2021-02-08 zhangkaibo@fibocom.com changed begin for mantis 0070613
|
||||
int interfacenum;
|
||||
//2021-02-08 zhangkaibo@fibocom.com changed end for mantis 0070613
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
RMNET_INFO rmnet_info;
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
} PROFILE_T;
|
||||
|
||||
typedef enum {
|
||||
SIM_ABSENT = 0,
|
||||
SIM_NOT_READY = 1,
|
||||
SIM_READY =
|
||||
2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
|
||||
SIM_PIN = 3,
|
||||
SIM_PUK = 4,
|
||||
SIM_NETWORK_PERSONALIZATION = 5,
|
||||
SIM_BAD = 6,
|
||||
} SIM_Status;
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
typedef enum {
|
||||
SIM_Card0 = 0,
|
||||
SIM_Card1 = 1
|
||||
} SIM_Select;
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
#define WDM_DEFAULT_BUFSIZE 256
|
||||
#define RIL_REQUEST_QUIT 0x1000
|
||||
#define RIL_INDICATE_DEVICE_CONNECTED 0x1002
|
||||
#define RIL_INDICATE_DEVICE_DISCONNECTED 0x1003
|
||||
#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 0x1004
|
||||
#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 0x1005
|
||||
|
||||
extern int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
unsigned msecs);
|
||||
extern int QmiThreadSendQMI(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse);
|
||||
extern int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse,
|
||||
unsigned msecs);
|
||||
extern void QmiThreadRecvQMI(PQCQMIMSG pResponse);
|
||||
extern int fibo_raw_ip_mode_check(const char *ifname);
|
||||
extern void udhcpc_start(PROFILE_T *profile);
|
||||
extern void udhcpc_stop(PROFILE_T *profile);
|
||||
extern void udhcpc_start_pcie(PROFILE_T *profile);
|
||||
extern void udhcpc_stop_pcie(PROFILE_T *profile);
|
||||
|
||||
extern void dump_qmi(void *dataBuffer, int dataLen);
|
||||
extern void qmidevice_send_event_to_main(int triger_event);
|
||||
extern int requestSetEthMode(PROFILE_T *profile);
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
//extern int requestGetSIMStatus(SIM_Status *pSIMStatus);
|
||||
extern int requestGetSIMStatus(SIM_Status *pSIMStatus , const int sim_select);
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
extern int requestEnterSimPin(const CHAR *pPinCode);
|
||||
extern int requestGetICCID(void);
|
||||
extern int requestGetIMSI(void);
|
||||
extern int requestRegistrationState(UCHAR *pPSAttachedState);
|
||||
extern int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily);
|
||||
extern int requestSetupDataCall(PROFILE_T *profile, int curIpFamily);
|
||||
extern int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily);
|
||||
extern int requestSetProfile(PROFILE_T *profile);
|
||||
extern int requestGetProfile(PROFILE_T *profile);
|
||||
extern int requestBaseBandVersion(const char **pp_reversion);
|
||||
extern int requestGetIPAddress(PROFILE_T *profile, int curIpFamily);
|
||||
extern int requestSetOperatingMode(UCHAR OperatingMode);
|
||||
int requestRegistrationState2(UCHAR *pPSAttachedState);
|
||||
|
||||
extern int fibo_qmap_mode_set(PROFILE_T *profile);
|
||||
extern int fibo_bridge_mode_detect(PROFILE_T *profile);
|
||||
extern int fibo_qmap_mode_detect(PROFILE_T *profile);
|
||||
extern const struct qmi_device_ops qmiwwan_qmidev_ops;
|
||||
|
||||
#define qmidev_is_gobinet(_qmichannel) \
|
||||
(strncmp(_qmichannel, "/dev/qcqmi", strlen("/dev/qcqmi")) == 0)
|
||||
#define qmidev_is_qmiwwan(_qmichannel) \
|
||||
(strncmp(_qmichannel, "/dev/cdc-wdm", strlen("/dev/cdc-wdm")) == 0)
|
||||
#define qmidev_is_pciemhi(_qmichannel) \
|
||||
(strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0)
|
||||
|
||||
#define driver_is_qmi(_drv_name) \
|
||||
(strncasecmp(_drv_name, "qmi_wwan", strlen("qmi_wwan")) == 0)
|
||||
#define driver_is_mbim(_drv_name) \
|
||||
(strncasecmp(_drv_name, "cdc_mbim", strlen("cdc_mbim")) == 0)
|
||||
|
||||
extern FILE *logfilefp;
|
||||
extern int debug_qmi;
|
||||
extern USHORT g_MobileCountryCode;
|
||||
extern USHORT g_MobileNetworkCode;
|
||||
extern int qmidevice_control_fd[2];
|
||||
extern int qmiclientId[QMUX_TYPE_WDS_ADMIN + 1];
|
||||
extern void dbg_time(const char *fmt, ...);
|
||||
extern USHORT le16_to_cpu(USHORT v16);
|
||||
extern UINT le32_to_cpu(UINT v32);
|
||||
extern USHORT cpu_to_le16(USHORT v16);
|
||||
extern UINT cpu_to_le32(UINT v32);
|
||||
#endif
|
||||
@@ -1,426 +0,0 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
typedef unsigned short sa_family_t;
|
||||
#include <linux/un.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
|
||||
#ifdef CONFIG_QMIWWAN
|
||||
#define FIBO_QMI_PROXY "fibo_qmimsg_server"
|
||||
static int cdc_wdm_fd = -1;
|
||||
|
||||
static UCHAR GetQCTLTransactionId(void)
|
||||
{
|
||||
static int TransactionId = 0;
|
||||
if (++TransactionId > 0xFF)
|
||||
TransactionId = 1;
|
||||
return TransactionId;
|
||||
}
|
||||
|
||||
typedef USHORT (*CUSTOMQCTL)(PQMICTL_MSG pCTLMsg, void *arg);
|
||||
|
||||
static PQCQMIMSG ComposeQCTLMsg(USHORT QMICTLType,
|
||||
CUSTOMQCTL customQctlMsgFunction, void *arg)
|
||||
{
|
||||
UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE];
|
||||
PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf;
|
||||
int Length;
|
||||
|
||||
pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
|
||||
pRequest->QMIHdr.CtlFlags = 0x00;
|
||||
pRequest->QMIHdr.QMIType = QMUX_TYPE_CTL;
|
||||
pRequest->QMIHdr.ClientId = 0x00;
|
||||
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST;
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.TransactionId = GetQCTLTransactionId();
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.QMICTLType = cpu_to_le16(QMICTLType);
|
||||
if (customQctlMsgFunction)
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.Length =
|
||||
cpu_to_le16(customQctlMsgFunction(&pRequest->CTLMsg, arg) -
|
||||
sizeof(QCQMICTL_MSG_HDR));
|
||||
else
|
||||
pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(0x0000);
|
||||
|
||||
pRequest->QMIHdr.Length =
|
||||
cpu_to_le16(le16_to_cpu(pRequest->CTLMsg.QMICTLMsgHdr.Length) +
|
||||
sizeof(QCQMICTL_MSG_HDR) + sizeof(QCQMI_HDR) - 1);
|
||||
Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1;
|
||||
|
||||
pRequest = (PQCQMIMSG)malloc(Length);
|
||||
if (pRequest == NULL) {
|
||||
dbg_time("%s fail to malloc", __func__);
|
||||
} else {
|
||||
memcpy(pRequest, QMIBuf, Length);
|
||||
}
|
||||
|
||||
return pRequest;
|
||||
}
|
||||
|
||||
static USHORT CtlGetVersionReq(PQMICTL_MSG QCTLMsg, void *arg)
|
||||
{
|
||||
QCTLMsg->GetVersionReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
|
||||
QCTLMsg->GetVersionReq.TLVLength = cpu_to_le16(0x0001);
|
||||
QCTLMsg->GetVersionReq.QMUXTypes = QMUX_TYPE_ALL;
|
||||
return sizeof(QMICTL_GET_VERSION_REQ_MSG);
|
||||
}
|
||||
|
||||
static USHORT CtlGetClientIdReq(PQMICTL_MSG QCTLMsg, void *arg)
|
||||
{
|
||||
QCTLMsg->GetClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
|
||||
QCTLMsg->GetClientIdReq.TLVLength = cpu_to_le16(0x0001);
|
||||
QCTLMsg->GetClientIdReq.QMIType = ((UCHAR *)arg)[0];
|
||||
return sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG);
|
||||
}
|
||||
|
||||
static USHORT CtlReleaseClientIdReq(PQMICTL_MSG QCTLMsg, void *arg)
|
||||
{
|
||||
QCTLMsg->ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
|
||||
QCTLMsg->ReleaseClientIdReq.TLVLength = cpu_to_le16(0x0002);
|
||||
QCTLMsg->ReleaseClientIdReq.QMIType = ((UCHAR *)arg)[0];
|
||||
QCTLMsg->ReleaseClientIdReq.ClientId = ((UCHAR *)arg)[1];
|
||||
return sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG);
|
||||
}
|
||||
|
||||
static int QmiWwanSendQMI(PQCQMIMSG pRequest)
|
||||
{
|
||||
struct pollfd pollfds[] = {{cdc_wdm_fd, POLLOUT, 0}};
|
||||
int ret;
|
||||
|
||||
if (cdc_wdm_fd == -1) {
|
||||
dbg_time("%s cdc_wdm_fd = -1", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pRequest->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6)
|
||||
pRequest->QMIHdr.QMIType = QMUX_TYPE_WDS;
|
||||
|
||||
do {
|
||||
ret = poll(pollfds, sizeof(pollfds) / sizeof(pollfds[0]), 5000);
|
||||
} while ((ret < 0) && (errno == EINTR));
|
||||
|
||||
if (pollfds[0].revents & POLLOUT) {
|
||||
ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1;
|
||||
ret = write(cdc_wdm_fd, pRequest, nwrites);
|
||||
if (ret == nwrites) {
|
||||
ret = 0;
|
||||
} else {
|
||||
dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
}
|
||||
} else {
|
||||
dbg_time("%s poll=%d, revents = 0x%x, errno: %d (%s)", __func__, ret,
|
||||
pollfds[0].revents, errno, strerror(errno));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int QmiWwanGetClientID(UCHAR QMIType)
|
||||
{
|
||||
PQCQMIMSG pResponse;
|
||||
|
||||
QmiThreadSendQMI(
|
||||
ComposeQCTLMsg(QMICTL_GET_CLIENT_ID_REQ, CtlGetClientIdReq, &QMIType),
|
||||
&pResponse);
|
||||
|
||||
if (pResponse) {
|
||||
USHORT QMUXResult = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp
|
||||
.QMUXResult); // QMI_RESULT_SUCCESS
|
||||
USHORT QMUXError = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp
|
||||
.QMUXError); // QMI_ERR_INVALID_ARG
|
||||
// UCHAR QMIType = pResponse->CTLMsg.GetClientIdRsp.QMIType;
|
||||
UCHAR ClientId = pResponse->CTLMsg.GetClientIdRsp.ClientId;
|
||||
|
||||
dbg_time("%s: QMIType = %d clientid %d", __func__, QMIType, ClientId);
|
||||
|
||||
if (!QMUXResult && !QMUXError &&
|
||||
(QMIType == pResponse->CTLMsg.GetClientIdRsp.QMIType)) {
|
||||
switch (QMIType) {
|
||||
case QMUX_TYPE_WDS:
|
||||
dbg_time("Get clientWDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_DMS:
|
||||
dbg_time("Get clientDMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_NAS:
|
||||
dbg_time("Get clientNAS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_QOS:
|
||||
dbg_time("Get clientQOS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WMS:
|
||||
dbg_time("Get clientWMS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_PDS:
|
||||
dbg_time("Get clientPDS = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_UIM:
|
||||
dbg_time("Get clientUIM = %d", ClientId);
|
||||
break;
|
||||
case QMUX_TYPE_WDS_ADMIN:
|
||||
dbg_time("Get clientWDA = %d", ClientId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ClientId;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int QmiWwanReleaseClientID(QMI_SERVICE_TYPE QMIType, UCHAR ClientId)
|
||||
{
|
||||
UCHAR argv[] = {QMIType, ClientId};
|
||||
QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_RELEASE_CLIENT_ID_REQ,
|
||||
CtlReleaseClientIdReq, argv),
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int QmiWwanInit(PROFILE_T *profile)
|
||||
{
|
||||
unsigned i;
|
||||
int ret;
|
||||
PQCQMIMSG pResponse;
|
||||
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1) {
|
||||
for (i = 0; i < 10; i++) {
|
||||
ret = QmiThreadSendQMITimeout(
|
||||
ComposeQCTLMsg(QMICTL_SYNC_REQ, NULL, NULL), NULL, 1 * 1000);
|
||||
if (!ret)
|
||||
break;
|
||||
sleep(1);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
QmiThreadSendQMI(
|
||||
ComposeQCTLMsg(QMICTL_GET_VERSION_REQ, CtlGetVersionReq, NULL),
|
||||
&pResponse);
|
||||
if (profile->qmap_mode) {
|
||||
if (pResponse) {
|
||||
if (pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 &&
|
||||
pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) {
|
||||
uint8_t NumElements = 0;
|
||||
|
||||
for (NumElements = 0;
|
||||
NumElements < pResponse->CTLMsg.GetVersionRsp.NumElements;
|
||||
NumElements++) {
|
||||
if (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements]
|
||||
.QMUXType == QMUX_TYPE_WDS_ADMIN)
|
||||
profile->qmap_version = (pResponse->CTLMsg.GetVersionRsp
|
||||
.TypeVersion[NumElements]
|
||||
.MinorVersion > 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pResponse)
|
||||
free(pResponse);
|
||||
if (profile->ipv4_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS] = QmiWwanGetClientID(QMUX_TYPE_WDS);
|
||||
if (profile->ipv6_flag)
|
||||
qmiclientId[QMUX_TYPE_WDS_IPV6] = QmiWwanGetClientID(QMUX_TYPE_WDS);
|
||||
qmiclientId[QMUX_TYPE_DMS] = QmiWwanGetClientID(QMUX_TYPE_DMS);
|
||||
qmiclientId[QMUX_TYPE_NAS] = QmiWwanGetClientID(QMUX_TYPE_NAS);
|
||||
qmiclientId[QMUX_TYPE_UIM] = QmiWwanGetClientID(QMUX_TYPE_UIM);
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1)
|
||||
qmiclientId[QMUX_TYPE_WDS_ADMIN] =
|
||||
QmiWwanGetClientID(QMUX_TYPE_WDS_ADMIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int QmiWwanDeInit(void)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) {
|
||||
if (qmiclientId[i] != 0) {
|
||||
QmiWwanReleaseClientID(i, qmiclientId[i]);
|
||||
qmiclientId[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qmi_proxy_open(const char *name)
|
||||
{
|
||||
int sockfd = -1;
|
||||
int reuse_addr = 1;
|
||||
struct sockaddr_un sockaddr;
|
||||
socklen_t alen;
|
||||
|
||||
/*Create server socket*/
|
||||
(sockfd = socket(AF_LOCAL, SOCK_STREAM, 0));
|
||||
if (sockfd < 0)
|
||||
return sockfd;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sun_family = AF_LOCAL;
|
||||
sockaddr.sun_path[0] = 0;
|
||||
memcpy(sockaddr.sun_path + 1, name, strlen(name));
|
||||
|
||||
alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1;
|
||||
if (connect(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) {
|
||||
close(sockfd);
|
||||
dbg_time("%s connect %s errno: %d (%s)\n", __func__, name, errno,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,
|
||||
sizeof(reuse_addr)));
|
||||
|
||||
dbg_time("connect to %s sockfd = %d\n", name, sockfd);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
static ssize_t qmi_proxy_read(int fd, void *buf, size_t size)
|
||||
{
|
||||
ssize_t nreads;
|
||||
PQCQMI_HDR pHdr = (PQCQMI_HDR)buf;
|
||||
|
||||
nreads = read(fd, pHdr, sizeof(QCQMI_HDR));
|
||||
if (nreads == sizeof(QCQMI_HDR)) {
|
||||
nreads += read(fd, pHdr + 1,
|
||||
le16_to_cpu(pHdr->Length) + 1 - sizeof(QCQMI_HDR));
|
||||
}
|
||||
|
||||
return nreads;
|
||||
}
|
||||
|
||||
static void *QmiWwanThread(void *pData)
|
||||
{
|
||||
PROFILE_T *profile = (PROFILE_T *)pData;
|
||||
const char *cdc_wdm = (const char *)profile->qmichannel;
|
||||
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1)
|
||||
cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
else
|
||||
cdc_wdm_fd = qmi_proxy_open(FIBO_QMI_PROXY);
|
||||
|
||||
if (cdc_wdm_fd == -1) {
|
||||
dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, cdc_wdm,
|
||||
errno, strerror(errno));
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fcntl(cdc_wdm_fd, F_SETFL, fcntl(cdc_wdm_fd, F_GETFL) | O_NONBLOCK);
|
||||
fcntl(cdc_wdm_fd, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
dbg_time("cdc_wdm_fd = %d", cdc_wdm_fd);
|
||||
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);
|
||||
|
||||
while (1) {
|
||||
struct pollfd pollfds[] = {{qmidevice_control_fd[1], POLLIN, 0},
|
||||
{cdc_wdm_fd, POLLIN, 0}};
|
||||
int ne, ret, nevents = sizeof(pollfds) / sizeof(pollfds[0]);
|
||||
|
||||
do {
|
||||
ret = poll(pollfds, nevents, -1);
|
||||
} while ((ret < 0) && (errno == EINTR));
|
||||
|
||||
if (ret <= 0) {
|
||||
dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
for (ne = 0; ne < nevents; ne++) {
|
||||
int fd = pollfds[ne].fd;
|
||||
short revents = pollfds[ne].revents;
|
||||
|
||||
// dbg_time("{%d, %x, %x}", pollfds[ne].fd, pollfds[ne].events,
|
||||
// pollfds[ne].revents);
|
||||
|
||||
if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||
dbg_time("%s poll err/hup/inval", __func__);
|
||||
dbg_time("poll fd = %d, events = 0x%04x", fd, revents);
|
||||
if (fd == cdc_wdm_fd) {
|
||||
} else {
|
||||
}
|
||||
if (revents &
|
||||
(POLLHUP | POLLNVAL)) // EC20 bug, Can get POLLERR
|
||||
goto __QmiWwanThread_quit;
|
||||
}
|
||||
|
||||
if ((revents & POLLIN) == 0)
|
||||
continue;
|
||||
|
||||
if (fd == qmidevice_control_fd[1]) {
|
||||
int triger_event;
|
||||
if (read(fd, &triger_event, sizeof(triger_event)) ==
|
||||
sizeof(triger_event)) {
|
||||
// DBG("triger_event = 0x%x", triger_event);
|
||||
switch (triger_event) {
|
||||
case RIL_REQUEST_QUIT:
|
||||
goto __QmiWwanThread_quit;
|
||||
break;
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
QmiThreadRecvQMI(NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fd == cdc_wdm_fd) {
|
||||
ssize_t nreads;
|
||||
UCHAR QMIBuf[4096];
|
||||
PQCQMIMSG pResponse = (PQCQMIMSG)QMIBuf;
|
||||
|
||||
if (profile->qmap_mode == 0 || profile->qmap_mode == 1)
|
||||
nreads = read(fd, QMIBuf, sizeof(QMIBuf));
|
||||
else
|
||||
nreads = qmi_proxy_read(fd, QMIBuf, sizeof(QMIBuf));
|
||||
// dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads,
|
||||
// errno, strerror(errno));
|
||||
if (nreads <= 0) {
|
||||
dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads,
|
||||
errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (nreads != (le16_to_cpu(pResponse->QMIHdr.Length) + 1)) {
|
||||
dbg_time("%s nreads=%d, pQCQMI->QMIHdr.Length = %d",
|
||||
__func__, (int)nreads,
|
||||
le16_to_cpu(pResponse->QMIHdr.Length));
|
||||
continue;
|
||||
}
|
||||
|
||||
QmiThreadRecvQMI(pResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__QmiWwanThread_quit:
|
||||
if (cdc_wdm_fd != -1) {
|
||||
close(cdc_wdm_fd);
|
||||
cdc_wdm_fd = -1;
|
||||
}
|
||||
qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
|
||||
QmiThreadRecvQMI(NULL); // main thread may pending on QmiThreadSendQMI()
|
||||
dbg_time("%s exit", __func__);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const struct qmi_device_ops qmiwwan_qmidev_ops = {
|
||||
.init = QmiWwanInit,
|
||||
.deinit = QmiWwanDeInit,
|
||||
.send = QmiWwanSendQMI,
|
||||
.read = QmiWwanThread,
|
||||
};
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert.
|
||||
#
|
||||
# Based on the busybox example scripts and the old udhcp source
|
||||
# package default.* scripts.
|
||||
|
||||
RESOLV_CONF="/etc/resolv.conf"
|
||||
|
||||
case $1 in
|
||||
bound|renew)
|
||||
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
|
||||
[ -n "$subnet" ] && NETMASK="netmask $subnet"
|
||||
|
||||
/sbin/ifconfig $interface $ip $BROADCAST $NETMASK
|
||||
|
||||
if [ -n "$router" ]; then
|
||||
echo "$0: Resetting default routes"
|
||||
while /sbin/route del default gw 0.0.0.0 dev $interface; do :; done
|
||||
|
||||
metric=0
|
||||
for i in $router; do
|
||||
/sbin/route add default gw $i dev $interface metric $metric
|
||||
metric=$(($metric + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
# Update resolver configuration file
|
||||
R=""
|
||||
[ -n "$domain" ] && R="domain $domain
|
||||
"
|
||||
for i in $dns; do
|
||||
echo "$0: Adding DNS $i"
|
||||
R="${R}nameserver $i
|
||||
"
|
||||
done
|
||||
|
||||
if [ -x /sbin/resolvconf ]; then
|
||||
echo -n "$R" | resolvconf -a "${interface}.udhcpc"
|
||||
else
|
||||
echo -n "$R" > "$RESOLV_CONF"
|
||||
fi
|
||||
;;
|
||||
|
||||
deconfig)
|
||||
if [ -x /sbin/resolvconf ]; then
|
||||
resolvconf -d "${interface}.udhcpc"
|
||||
fi
|
||||
/sbin/ifconfig $interface 0.0.0.0
|
||||
;;
|
||||
|
||||
leasefail)
|
||||
echo "$0: Lease failed: $message"
|
||||
;;
|
||||
|
||||
nak)
|
||||
echo "$0: Received a NAK: $message"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "$0: Unknown udhcpc command: $1";
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,28 +0,0 @@
|
||||
= What is libmnl? =
|
||||
|
||||
libmnl is a minimalistic user-space library oriented to Netlink developers.
|
||||
There are a lot of common tasks in parsing, validating, constructing of
|
||||
both the Netlink header and TLVs that are repetitive and easy to get wrong.
|
||||
This library aims to provide simple helpers that allows you to re-use code
|
||||
and to avoid re-inventing the wheel. The main features of this library are:
|
||||
|
||||
* Small: the shared library requires around 30KB for an x86-based computer.
|
||||
* Simple: this library avoids complexity and elaborated abstractions that
|
||||
tend to hide Netlink details.
|
||||
* Easy to use: the library simplifies the work for Netlink-wise developers.
|
||||
It provides functions to make socket handling, message building, validating,
|
||||
parsing and sequence tracking, easier.
|
||||
* Easy to re-use: you can use the library to build your own abstraction layer
|
||||
on top of this library.
|
||||
* Decoupling: the interdependency of the main bricks that compose the library
|
||||
is reduced, i.e. the library provides many helpers, but the programmer is not
|
||||
forced to use them.
|
||||
|
||||
= Example files =
|
||||
|
||||
You can find several example files under examples/ that you can compile by
|
||||
invoking `make check'.
|
||||
|
||||
--
|
||||
08/sep/2010
|
||||
Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
@@ -1,722 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <limits.h> /* for INT_MAX */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
/**
|
||||
* \defgroup attr Netlink attribute helpers
|
||||
*
|
||||
* Netlink Type-Length-Value (TLV) attribute:
|
||||
* \verbatim
|
||||
|<-- 2 bytes -->|<-- 2 bytes -->|<-- variable -->|
|
||||
-------------------------------------------------
|
||||
| length | type | value |
|
||||
-------------------------------------------------
|
||||
|<--------- header ------------>|<-- payload --->|
|
||||
\endverbatim
|
||||
* The payload of the Netlink message contains sequences of attributes that are
|
||||
* expressed in TLV format.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_attr_get_type - get type of netlink attribute
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the attribute type.
|
||||
*/
|
||||
uint16_t mnl_attr_get_type(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_type & NLA_TYPE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_len - get length of netlink attribute
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the attribute length that is the attribute header
|
||||
* plus the attribute payload.
|
||||
*/
|
||||
uint16_t mnl_attr_get_len(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_payload_len - get the attribute payload-value length
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the attribute payload-value length.
|
||||
*/
|
||||
uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_len - MNL_ATTR_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_payload - get pointer to the attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function return a pointer to the attribute payload.
|
||||
*/
|
||||
void *mnl_attr_get_payload(const struct nlattr *attr)
|
||||
{
|
||||
return (void *)attr + MNL_ATTR_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_ok - check if there is room for an attribute in a buffer
|
||||
* \param attr attribute that we want to check if there is room for
|
||||
* \param len remaining bytes in a buffer that contains the attribute
|
||||
*
|
||||
* This function is used to check that a buffer, which is supposed to contain
|
||||
* an attribute, has enough room for the attribute that it stores, i.e. this
|
||||
* function can be used to verify that an attribute is neither malformed nor
|
||||
* truncated.
|
||||
*
|
||||
* This function does not set errno in case of error since it is intended
|
||||
* for iterations. Thus, it returns true on success and false on error.
|
||||
*
|
||||
* The len parameter may be negative in the case of malformed messages during
|
||||
* attribute iteration, that is why we use a signed integer.
|
||||
*/
|
||||
bool mnl_attr_ok(const struct nlattr *attr, int len)
|
||||
{
|
||||
return len >= (int)sizeof(struct nlattr) &&
|
||||
attr->nla_len >= sizeof(struct nlattr) &&
|
||||
(int)attr->nla_len <= len;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_next - get the next attribute in the payload of a netlink message
|
||||
* \param attr pointer to the current attribute
|
||||
*
|
||||
* This function returns a pointer to the next attribute after the one passed
|
||||
* as parameter. You have to use mnl_attr_ok() to ensure that the next
|
||||
* attribute is valid.
|
||||
*/
|
||||
struct nlattr *mnl_attr_next(const struct nlattr *attr)
|
||||
{
|
||||
return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_type_valid - check if the attribute type is valid
|
||||
* \param attr pointer to attribute to be checked
|
||||
* \param max maximum attribute type
|
||||
*
|
||||
* This function allows to check if the attribute type is higher than the
|
||||
* maximum supported type. If the attribute type is invalid, this function
|
||||
* returns -1 and errno is explicitly set. On success, this function returns 1.
|
||||
*
|
||||
* Strict attribute checking in user-space is not a good idea since you may
|
||||
* run an old application with a newer kernel that supports new attributes.
|
||||
* This leads to backward compatibility breakages in user-space. Better check
|
||||
* if you support an attribute, if not, skip it.
|
||||
*/
|
||||
int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
|
||||
{
|
||||
if (mnl_attr_get_type(attr) > max) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __mnl_attr_validate(const struct nlattr *attr,
|
||||
enum mnl_attr_data_type type, size_t exp_len)
|
||||
{
|
||||
uint16_t attr_len = mnl_attr_get_payload_len(attr);
|
||||
const char *attr_data = mnl_attr_get_payload(attr);
|
||||
|
||||
if (attr_len < exp_len) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
switch(type) {
|
||||
case MNL_TYPE_FLAG:
|
||||
if (attr_len > 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
if (attr_len == 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
if (attr_data[attr_len-1] != '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_STRING:
|
||||
if (attr_len == 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_NESTED:
|
||||
/* empty nested attributes are OK. */
|
||||
if (attr_len == 0)
|
||||
break;
|
||||
/* if not empty, they must contain one header, eg. flag */
|
||||
if (attr_len < MNL_ATTR_HDRLEN) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* make gcc happy. */
|
||||
break;
|
||||
}
|
||||
if (exp_len && attr_len > exp_len) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
|
||||
[MNL_TYPE_U8] = sizeof(uint8_t),
|
||||
[MNL_TYPE_U16] = sizeof(uint16_t),
|
||||
[MNL_TYPE_U32] = sizeof(uint32_t),
|
||||
[MNL_TYPE_U64] = sizeof(uint64_t),
|
||||
[MNL_TYPE_MSECS] = sizeof(uint64_t),
|
||||
};
|
||||
|
||||
/**
|
||||
* mnl_attr_validate - validate netlink attribute (simplified version)
|
||||
* \param attr pointer to netlink attribute that we want to validate
|
||||
* \param type data type (see enum mnl_attr_data_type)
|
||||
*
|
||||
* The validation is based on the data type. Specifically, it checks that
|
||||
* integers (u8, u16, u32 and u64) have enough room for them. This function
|
||||
* returns -1 in case of error, and errno is explicitly set.
|
||||
*/
|
||||
int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
|
||||
{
|
||||
int exp_len;
|
||||
|
||||
if (type >= MNL_TYPE_MAX) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
exp_len = mnl_attr_data_type_len[type];
|
||||
return __mnl_attr_validate(attr, type, exp_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_validate2 - validate netlink attribute (extended version)
|
||||
* \param attr pointer to netlink attribute that we want to validate
|
||||
* \param type attribute type (see enum mnl_attr_data_type)
|
||||
* \param exp_len expected attribute data size
|
||||
*
|
||||
* This function allows to perform a more accurate validation for attributes
|
||||
* whose size is variable. If the size of the attribute is not what we expect,
|
||||
* this functions returns -1 and errno is explicitly set.
|
||||
*/
|
||||
int mnl_attr_validate2(const struct nlattr *attr,
|
||||
enum mnl_attr_data_type type,
|
||||
size_t exp_len)
|
||||
{
|
||||
if (type >= MNL_TYPE_MAX) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return __mnl_attr_validate(attr, type, exp_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_parse - parse attributes
|
||||
* \param nlh pointer to netlink message
|
||||
* \param offset offset to start parsing from (if payload is after any header)
|
||||
* \param cb callback function that is called for each attribute
|
||||
* \param data pointer to data that is passed to the callback function
|
||||
*
|
||||
* This function allows to iterate over the sequence of attributes that compose
|
||||
* the Netlink message. You can then put the attribute in an array as it
|
||||
* usually happens at this stage or you can use any other data structure (such
|
||||
* as lists or trees).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
int mnl_attr_parse(const struct nlmsghdr *nlh,
|
||||
unsigned int offset, mnl_attr_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each(attr, nlh, offset)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_parse_nested - parse attributes inside a nest
|
||||
* \param nested pointer to netlink attribute that contains a nest
|
||||
* \param cb callback function that is called for each attribute in the nest
|
||||
* \param data pointer to data passed to the callback function
|
||||
*
|
||||
* This function allows to iterate over the sequence of attributes that compose
|
||||
* the Netlink message. You can then put the attribute in an array as it
|
||||
* usually happens at this stage or you can use any other data structure (such
|
||||
* as lists or trees).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
int mnl_attr_parse_nested(const struct nlattr *nested,
|
||||
mnl_attr_cb_t cb, void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each_nested(attr, nested)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_parse_payload - parse attributes in payload of Netlink message
|
||||
* \param payload pointer to payload of the Netlink message
|
||||
* \param payload_len payload length that contains the attributes
|
||||
* \param cb callback function that is called for each attribute
|
||||
* \param data pointer to data that is passed to the callback function
|
||||
*
|
||||
* This function takes a pointer to the area that contains the attributes,
|
||||
* commonly known as the payload of the Netlink message. Thus, you have to
|
||||
* pass a pointer to the Netlink message payload, instead of the entire
|
||||
* message.
|
||||
*
|
||||
* This function allows you to iterate over the sequence of attributes that are
|
||||
* located at some payload offset. You can then put the attributes in one array
|
||||
* as usual, or you can use any other data structure (such as lists or trees).
|
||||
*
|
||||
* This function propagates the return value of the callback, which can be
|
||||
* MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
|
||||
*/
|
||||
int mnl_attr_parse_payload(const void *payload,
|
||||
size_t payload_len,
|
||||
mnl_attr_cb_t cb, void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each_payload(payload, payload_len)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u8 - returns 8-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 8-bit value of the attribute payload.
|
||||
*/
|
||||
uint8_t mnl_attr_get_u8(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint8_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u16 - returns 16-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 16-bit value of the attribute payload.
|
||||
*/
|
||||
uint16_t mnl_attr_get_u16(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint16_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u32 - returns 32-bit unsigned integer attribute payload
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 32-bit value of the attribute payload.
|
||||
*/
|
||||
uint32_t mnl_attr_get_u32(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint32_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_u64 - returns 64-bit unsigned integer attribute.
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the 64-bit value of the attribute payload. This
|
||||
* function is align-safe, since accessing 64-bit Netlink attributes is a
|
||||
* common source of alignment issues.
|
||||
*/
|
||||
uint64_t mnl_attr_get_u64(const struct nlattr *attr)
|
||||
{
|
||||
uint64_t tmp;
|
||||
memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_get_str - returns pointer to string attribute.
|
||||
* \param attr pointer to netlink attribute
|
||||
*
|
||||
* This function returns the payload of string attribute value.
|
||||
*/
|
||||
const char *mnl_attr_get_str(const struct nlattr *attr)
|
||||
{
|
||||
return mnl_attr_get_payload(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put - add an attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type that you want to add
|
||||
* \param len netlink attribute payload length
|
||||
* \param data pointer to the data that will be stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
|
||||
size_t len, const void *data)
|
||||
{
|
||||
struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
|
||||
uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
|
||||
int pad;
|
||||
|
||||
attr->nla_type = type;
|
||||
attr->nla_len = payload_len;
|
||||
memcpy(mnl_attr_get_payload(attr), data, len);
|
||||
pad = MNL_ALIGN(len) - len;
|
||||
if (pad > 0)
|
||||
memset(mnl_attr_get_payload(attr) + len, 0, pad);
|
||||
|
||||
nlh->nlmsg_len += MNL_ALIGN(payload_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 8-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint8_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 16-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint16_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 32-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint32_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data 64-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
|
||||
uint64_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_str - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
|
||||
const char *data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, strlen(data), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_strz - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function is similar to mnl_attr_put_str, but it includes the
|
||||
* NUL/zero ('\0') terminator at the end of the string.
|
||||
*
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
|
||||
const char *data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, strlen(data)+1, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_start - start an attribute nest
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
*
|
||||
* This function adds the attribute header that identifies the beginning of
|
||||
* an attribute nest. This function always returns a valid pointer to the
|
||||
* beginning of the nest.
|
||||
*/
|
||||
struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
|
||||
uint16_t type)
|
||||
{
|
||||
struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
|
||||
|
||||
/* set start->nla_len in mnl_attr_nest_end() */
|
||||
start->nla_type = NLA_F_NESTED | type;
|
||||
nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_check - add an attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type that you want to add
|
||||
* \param len netlink attribute payload length
|
||||
* \param data pointer to the data that will be stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, size_t len,
|
||||
const void *data)
|
||||
{
|
||||
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
|
||||
return false;
|
||||
mnl_attr_put(nlh, type, len, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 8-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint8_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 16-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint16_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 32-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint32_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data 64-bit unsigned integer data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint64_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_str_check - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
* This function updates the length field of the Netlink message (nlmsg_len)
|
||||
* by adding the size (header + payload) of the new attribute.
|
||||
*/
|
||||
bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, const char *data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_put_strz_check - add string attribute to netlink message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param type netlink attribute type
|
||||
* \param data pointer to string data that is stored by the new attribute
|
||||
*
|
||||
* This function is similar to mnl_attr_put_str, but it includes the
|
||||
* NUL/zero ('\0') terminator at the end of the string.
|
||||
*
|
||||
* This function first checks that the data can be added to the message
|
||||
* (fits into the buffer) and then updates the length field of the Netlink
|
||||
* message (nlmsg_len) by adding the size (header + payload) of the new
|
||||
* attribute. The function returns true if the attribute could be added
|
||||
* to the message, otherwise false is returned.
|
||||
*/
|
||||
bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, const char *data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_start_check - start an attribute nest
|
||||
* \param buflen size of buffer which stores the message
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param type netlink attribute type
|
||||
*
|
||||
* This function adds the attribute header that identifies the beginning of
|
||||
* an attribute nest. If the nested attribute cannot be added then NULL,
|
||||
* otherwise valid pointer to the beginning of the nest is returned.
|
||||
*/
|
||||
struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
|
||||
size_t buflen,
|
||||
uint16_t type)
|
||||
{
|
||||
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
|
||||
return NULL;
|
||||
return mnl_attr_nest_start(nlh, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_end - end an attribute nest
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param start pointer to the attribute nest returned by mnl_attr_nest_start()
|
||||
*
|
||||
* This function updates the attribute header that identifies the nest.
|
||||
*/
|
||||
void mnl_attr_nest_end(struct nlmsghdr *nlh,
|
||||
struct nlattr *start)
|
||||
{
|
||||
start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_attr_nest_cancel - cancel an attribute nest
|
||||
* \param nlh pointer to the netlink message
|
||||
* \param start pointer to the attribute nest returned by mnl_attr_nest_start()
|
||||
*
|
||||
* This function updates the attribute header that identifies the nest.
|
||||
*/
|
||||
void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
|
||||
struct nlattr *start)
|
||||
{
|
||||
nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int mnl_cb_error(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||
|
||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
|
||||
errno = EBADMSG;
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
/* Netlink subsystems returns the errno value with different signess */
|
||||
if (err->error < 0)
|
||||
errno = -err->error;
|
||||
else
|
||||
errno = err->error;
|
||||
|
||||
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
return MNL_CB_STOP;
|
||||
}
|
||||
|
||||
static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
|
||||
[NLMSG_NOOP] = mnl_cb_noop,
|
||||
[NLMSG_ERROR] = mnl_cb_error,
|
||||
[NLMSG_DONE] = mnl_cb_stop,
|
||||
[NLMSG_OVERRUN] = mnl_cb_noop,
|
||||
};
|
||||
|
||||
static inline int __mnl_cb_run(const void *buf, size_t numbytes,
|
||||
unsigned int seq, unsigned int portid,
|
||||
mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len)
|
||||
{
|
||||
int ret = MNL_CB_OK, len = numbytes;
|
||||
const struct nlmsghdr *nlh = buf;
|
||||
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
/* check message source */
|
||||
if (!mnl_nlmsg_portid_ok(nlh, portid)) {
|
||||
errno = ESRCH;
|
||||
return -1;
|
||||
}
|
||||
/* perform sequence tracking */
|
||||
if (!mnl_nlmsg_seq_ok(nlh, seq)) {
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* dump was interrupted */
|
||||
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* netlink data message handling */
|
||||
if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
|
||||
if (cb_data){
|
||||
ret = cb_data(nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
} else if (nlh->nlmsg_type < cb_ctl_array_len) {
|
||||
if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
|
||||
ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
} else if (default_cb_array[nlh->nlmsg_type]) {
|
||||
ret = default_cb_array[nlh->nlmsg_type](nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
nlh = mnl_nlmsg_next(nlh, &len);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \defgroup callback Callback helpers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_cb_run2 - callback runqueue for netlink messages
|
||||
* \param buf buffer that contains the netlink messages
|
||||
* \param numbytes number of bytes stored in the buffer
|
||||
* \param seq sequence number that we expect to receive
|
||||
* \param portid Netlink PortID that we expect to receive
|
||||
* \param cb_data callback handler for data messages
|
||||
* \param data pointer to data that will be passed to the data callback handler
|
||||
* \param cb_ctl_array array of custom callback handlers from control messages
|
||||
* \param cb_ctl_array_len array length of custom control callback handlers
|
||||
*
|
||||
* You can set the cb_ctl_array to NULL if you want to use the default control
|
||||
* callback handlers, in that case, the parameter cb_ctl_array_len is not
|
||||
* checked.
|
||||
*
|
||||
* Your callback may return three possible values:
|
||||
* - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
|
||||
* - MNL_CB_STOP (=0): stop callback runqueue.
|
||||
* - MNL_CB_OK (>=1): no problem has occurred.
|
||||
*
|
||||
* This function propagates the callback return value. On error, it returns
|
||||
* -1 and errno is explicitly set. If the portID is not the expected, errno
|
||||
* is set to ESRCH. If the sequence number is not the expected, errno is set
|
||||
* to EPROTO. If the dump was interrupted, errno is set to EINTR and you should
|
||||
* request a new fresh dump again.
|
||||
*/
|
||||
int mnl_cb_run2(const void *buf, size_t numbytes,
|
||||
unsigned int seq, unsigned int portid,
|
||||
mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len)
|
||||
{
|
||||
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
|
||||
cb_ctl_array, cb_ctl_array_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_cb_run - callback runqueue for netlink messages (simplified version)
|
||||
* \param buf buffer that contains the netlink messages
|
||||
* \param numbytes number of bytes stored in the buffer
|
||||
* \param seq sequence number that we expect to receive
|
||||
* \param portid Netlink PortID that we expect to receive
|
||||
* \param cb_data callback handler for data messages
|
||||
* \param data pointer to data that will be passed to the data callback handler
|
||||
*
|
||||
* This function is like mnl_cb_run2() but it does not allow you to set
|
||||
* the control callback handlers.
|
||||
*
|
||||
* Your callback may return three possible values:
|
||||
* - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
|
||||
* - MNL_CB_STOP (=0): stop callback runqueue.
|
||||
* - MNL_CB_OK (>=1): no problems has occurred.
|
||||
*
|
||||
* This function propagates the callback return value.
|
||||
*/
|
||||
int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data)
|
||||
{
|
||||
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -1,5 +0,0 @@
|
||||
#ifndef __DHCP_H__
|
||||
#define __DHCP_H__
|
||||
|
||||
int do_dhcp(char *iname);
|
||||
#endif //__DHCP_H__
|
||||
@@ -1,515 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include "../ifutils.h"
|
||||
#include "dhcpmsg.h"
|
||||
#include "packet.h"
|
||||
|
||||
#define VERBOSE 2
|
||||
|
||||
static int verbose = 1;
|
||||
static char errmsg[2048];
|
||||
|
||||
typedef unsigned long long msecs_t;
|
||||
#if VERBOSE
|
||||
void dump_dhcp_msg();
|
||||
#endif
|
||||
|
||||
msecs_t get_msecs(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
|
||||
return 0;
|
||||
} else {
|
||||
return (((msecs_t) ts.tv_sec) * ((msecs_t) 1000)) +
|
||||
(((msecs_t) ts.tv_nsec) / ((msecs_t) 1000000));
|
||||
}
|
||||
}
|
||||
|
||||
void printerr(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(errmsg, sizeof(errmsg), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
printf("%s\n", errmsg);
|
||||
}
|
||||
|
||||
const char *dhcp_lasterror()
|
||||
{
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
int fatal(const char *reason)
|
||||
{
|
||||
printerr("%s: %s\n", reason, strerror(errno));
|
||||
return -1;
|
||||
// exit(1);
|
||||
}
|
||||
|
||||
typedef struct dhcp_info dhcp_info;
|
||||
|
||||
struct dhcp_info {
|
||||
uint32_t type;
|
||||
|
||||
uint32_t ipaddr;
|
||||
uint32_t gateway;
|
||||
uint32_t prefixLength;
|
||||
|
||||
uint32_t dns1;
|
||||
uint32_t dns2;
|
||||
|
||||
uint32_t serveraddr;
|
||||
uint32_t lease;
|
||||
};
|
||||
|
||||
dhcp_info last_good_info;
|
||||
|
||||
void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *prefixLength,
|
||||
uint32_t *dns1, uint32_t *dns2, uint32_t *server,
|
||||
uint32_t *lease)
|
||||
{
|
||||
*ipaddr = last_good_info.ipaddr;
|
||||
*gateway = last_good_info.gateway;
|
||||
*prefixLength = last_good_info.prefixLength;
|
||||
*dns1 = last_good_info.dns1;
|
||||
*dns2 = last_good_info.dns2;
|
||||
*server = last_good_info.serveraddr;
|
||||
*lease = last_good_info.lease;
|
||||
}
|
||||
|
||||
static int dhcp_configure(const char *ifname, dhcp_info *info)
|
||||
{
|
||||
last_good_info = *info;
|
||||
return if_set_network_v4(ifname, info->ipaddr, info->prefixLength, info->gateway,
|
||||
info->dns1, info->dns2);
|
||||
}
|
||||
|
||||
static const char *dhcp_type_to_name(uint32_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case DHCPDISCOVER: return "discover";
|
||||
case DHCPOFFER: return "offer";
|
||||
case DHCPREQUEST: return "request";
|
||||
case DHCPDECLINE: return "decline";
|
||||
case DHCPACK: return "ack";
|
||||
case DHCPNAK: return "nak";
|
||||
case DHCPRELEASE: return "release";
|
||||
case DHCPINFORM: return "inform";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
void dump_dhcp_info(dhcp_info *info)
|
||||
{
|
||||
char addr[20], gway[20];
|
||||
printf("--- dhcp %s (%d) ---\n",
|
||||
dhcp_type_to_name(info->type), info->type);
|
||||
strcpy(addr, ipaddr_to_string_v4(info->ipaddr));
|
||||
strcpy(gway, ipaddr_to_string_v4(info->gateway));
|
||||
printf("ip %s gw %s prefixLength %d\n", addr, gway, info->prefixLength);
|
||||
if (info->dns1) printf("dns1: %s\n", ipaddr_to_string_v4(info->dns1));
|
||||
if (info->dns2) printf("dns2: %s\n", ipaddr_to_string_v4(info->dns2));
|
||||
printf("server %s, lease %d seconds\n",
|
||||
ipaddr_to_string_v4(info->serveraddr), info->lease);
|
||||
}
|
||||
|
||||
|
||||
int decode_dhcp_msg(dhcp_msg *msg, int len, dhcp_info *info)
|
||||
{
|
||||
uint8_t *x;
|
||||
unsigned int opt;
|
||||
int optlen;
|
||||
|
||||
memset(info, 0, sizeof(dhcp_info));
|
||||
if (len < (DHCP_MSG_FIXED_SIZE + 4)) return -1;
|
||||
|
||||
len -= (DHCP_MSG_FIXED_SIZE + 4);
|
||||
|
||||
if (msg->options[0] != OPT_COOKIE1) return -1;
|
||||
if (msg->options[1] != OPT_COOKIE2) return -1;
|
||||
if (msg->options[2] != OPT_COOKIE3) return -1;
|
||||
if (msg->options[3] != OPT_COOKIE4) return -1;
|
||||
|
||||
x = msg->options + 4;
|
||||
|
||||
while (len > 2) {
|
||||
opt = *x++;
|
||||
if (opt == OPT_PAD) {
|
||||
len--;
|
||||
continue;
|
||||
}
|
||||
if (opt == OPT_END) {
|
||||
break;
|
||||
}
|
||||
optlen = *x++;
|
||||
len -= 2;
|
||||
if (optlen > len) {
|
||||
break;
|
||||
}
|
||||
switch(opt) {
|
||||
case OPT_SUBNET_MASK:
|
||||
if (optlen >= 4) {
|
||||
in_addr_t mask;
|
||||
memcpy(&mask, x, 4);
|
||||
info->prefixLength = mask_to_prefix_v4(mask);
|
||||
}
|
||||
break;
|
||||
case OPT_GATEWAY:
|
||||
if (optlen >= 4) memcpy(&info->gateway, x, 4);
|
||||
break;
|
||||
case OPT_DNS:
|
||||
if (optlen >= 4) memcpy(&info->dns1, x + 0, 4);
|
||||
if (optlen >= 8) memcpy(&info->dns2, x + 4, 4);
|
||||
break;
|
||||
case OPT_LEASE_TIME:
|
||||
if (optlen >= 4) {
|
||||
memcpy(&info->lease, x, 4);
|
||||
info->lease = ntohl(info->lease);
|
||||
}
|
||||
break;
|
||||
case OPT_SERVER_ID:
|
||||
if (optlen >= 4) memcpy(&info->serveraddr, x, 4);
|
||||
break;
|
||||
case OPT_MESSAGE_TYPE:
|
||||
info->type = *x;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
x += optlen;
|
||||
len -= optlen;
|
||||
}
|
||||
|
||||
info->ipaddr = msg->yiaddr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if VERBOSE
|
||||
|
||||
static void hex2str(char *buf, size_t buf_size, const unsigned char *array, int len)
|
||||
{
|
||||
int i;
|
||||
char *cp = buf;
|
||||
char *buf_end = buf + buf_size;
|
||||
for (i = 0; i < len; i++) {
|
||||
cp += snprintf(cp, buf_end - cp, " %02x ", array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_dhcp_msg(dhcp_msg *msg, int len)
|
||||
{
|
||||
unsigned char *x;
|
||||
unsigned int n,c;
|
||||
int optsz;
|
||||
const char *name;
|
||||
char buf[2048];
|
||||
|
||||
if (len < DHCP_MSG_FIXED_SIZE) {
|
||||
printf("Invalid length %d, should be %d", len, DHCP_MSG_FIXED_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
len -= DHCP_MSG_FIXED_SIZE;
|
||||
|
||||
if (msg->op == OP_BOOTREQUEST)
|
||||
name = "BOOTREQUEST";
|
||||
else if (msg->op == OP_BOOTREPLY)
|
||||
name = "BOOTREPLY";
|
||||
else
|
||||
name = "????";
|
||||
|
||||
c = msg->hlen > 16 ? 16 : msg->hlen;
|
||||
hex2str(buf, sizeof(buf), msg->chaddr, c);
|
||||
|
||||
for (n = 0; n < 64; n++) {
|
||||
unsigned char x = msg->sname[n];
|
||||
if ((x < ' ') || (x > 127)) {
|
||||
if (x == 0) break;
|
||||
msg->sname[n] = '.';
|
||||
}
|
||||
}
|
||||
msg->sname[63] = 0;
|
||||
|
||||
for (n = 0; n < 128; n++) {
|
||||
unsigned char x = msg->file[n];
|
||||
if ((x < ' ') || (x > 127)) {
|
||||
if (x == 0) break;
|
||||
msg->file[n] = '.';
|
||||
}
|
||||
}
|
||||
msg->file[127] = 0;
|
||||
|
||||
if (len < 4) return;
|
||||
len -= 4;
|
||||
x = msg->options + 4;
|
||||
|
||||
while (len > 2) {
|
||||
if (*x == 0) {
|
||||
x++;
|
||||
len--;
|
||||
continue;
|
||||
}
|
||||
if (*x == OPT_END) {
|
||||
break;
|
||||
}
|
||||
len -= 2;
|
||||
optsz = x[1];
|
||||
if (optsz > len) break;
|
||||
if (x[0] == OPT_DOMAIN_NAME || x[0] == OPT_MESSAGE) {
|
||||
if ((unsigned int)optsz < sizeof(buf) - 1) {
|
||||
n = optsz;
|
||||
} else {
|
||||
n = sizeof(buf) - 1;
|
||||
}
|
||||
memcpy(buf, &x[2], n);
|
||||
buf[n] = '\0';
|
||||
} else {
|
||||
hex2str(buf, sizeof(buf), &x[2], optsz);
|
||||
}
|
||||
if (x[0] == OPT_MESSAGE_TYPE)
|
||||
name = dhcp_type_to_name(x[2]);
|
||||
else
|
||||
name = NULL;
|
||||
len -= optsz;
|
||||
x = x + optsz + 2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int send_message(int sock, int if_index, dhcp_msg *msg, int size)
|
||||
{
|
||||
#if VERBOSE > 1
|
||||
dump_dhcp_msg(msg, size);
|
||||
#endif
|
||||
return send_packet(sock, if_index, msg, size, INADDR_ANY, INADDR_BROADCAST,
|
||||
PORT_BOOTP_CLIENT, PORT_BOOTP_SERVER);
|
||||
}
|
||||
|
||||
static int is_valid_reply(dhcp_msg *msg, dhcp_msg *reply, int sz)
|
||||
{
|
||||
if (sz < DHCP_MSG_FIXED_SIZE) {
|
||||
if (verbose) printf("Wrong size %d != %d\n", sz, DHCP_MSG_FIXED_SIZE);
|
||||
return 0;
|
||||
}
|
||||
if (reply->op != OP_BOOTREPLY) {
|
||||
if (verbose) printf("Wrong Op %d != %d\n", reply->op, OP_BOOTREPLY);
|
||||
return 0;
|
||||
}
|
||||
if (reply->xid != msg->xid) {
|
||||
if (verbose) printf("Wrong Xid 0x%x != 0x%x\n", ntohl(reply->xid),
|
||||
ntohl(msg->xid));
|
||||
return 0;
|
||||
}
|
||||
if (reply->htype != msg->htype) {
|
||||
if (verbose) printf("Wrong Htype %d != %d\n", reply->htype, msg->htype);
|
||||
return 0;
|
||||
}
|
||||
if (reply->hlen != msg->hlen) {
|
||||
if (verbose) printf("Wrong Hlen %d != %d\n", reply->hlen, msg->hlen);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(msg->chaddr, reply->chaddr, msg->hlen)) {
|
||||
if (verbose) printf("Wrong chaddr %x != %x\n", *(reply->chaddr),*(msg->chaddr));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define STATE_SELECTING 1
|
||||
#define STATE_REQUESTING 2
|
||||
|
||||
#define TIMEOUT_INITIAL 4000
|
||||
#define TIMEOUT_MAX 32000
|
||||
|
||||
int dhcp_init_ifc(const char *ifname)
|
||||
{
|
||||
dhcp_msg discover_msg;
|
||||
dhcp_msg request_msg;
|
||||
dhcp_msg reply;
|
||||
dhcp_msg *msg;
|
||||
dhcp_info info;
|
||||
int s, r, size;
|
||||
int valid_reply;
|
||||
uint32_t xid;
|
||||
unsigned char hwaddr[6];
|
||||
struct pollfd pfd;
|
||||
unsigned int state;
|
||||
unsigned int timeout;
|
||||
int if_index;
|
||||
|
||||
xid = (uint32_t) get_msecs();
|
||||
|
||||
if (if_get_hwaddr(ifname, hwaddr)) {
|
||||
return fatal("cannot obtain interface address");
|
||||
}
|
||||
if ((if_index = if_nametoindex(ifname)) == 0) {
|
||||
return fatal("cannot obtain interface index");
|
||||
}
|
||||
|
||||
s = open_raw_socket(ifname, hwaddr, if_index);
|
||||
|
||||
timeout = TIMEOUT_INITIAL;
|
||||
state = STATE_SELECTING;
|
||||
info.type = 0;
|
||||
goto transmit;
|
||||
|
||||
for (;;) {
|
||||
pfd.fd = s;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
r = poll(&pfd, 1, timeout);
|
||||
|
||||
if (r == 0) {
|
||||
#if VERBOSE
|
||||
printerr("TIMEOUT\n");
|
||||
#endif
|
||||
if (timeout >= TIMEOUT_MAX) {
|
||||
printerr("timed out\n");
|
||||
if ( info.type == DHCPOFFER ) {
|
||||
printerr("no acknowledgement from DHCP server\nconfiguring %s with offered parameters\n", ifname);
|
||||
return dhcp_configure(ifname, &info);
|
||||
}
|
||||
errno = ETIME;
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
timeout = timeout * 2;
|
||||
|
||||
transmit:
|
||||
size = 0;
|
||||
msg = NULL;
|
||||
switch(state) {
|
||||
case STATE_SELECTING:
|
||||
msg = &discover_msg;
|
||||
size = init_dhcp_discover_msg(msg, hwaddr, xid);
|
||||
break;
|
||||
case STATE_REQUESTING:
|
||||
msg = &request_msg;
|
||||
size = init_dhcp_request_msg(msg, hwaddr, xid, info.ipaddr, info.serveraddr);
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
}
|
||||
if (size != 0) {
|
||||
r = send_message(s, if_index, msg, size);
|
||||
if (r < 0) {
|
||||
printerr("error sending dhcp msg: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if ((errno == EAGAIN) || (errno == EINTR)) {
|
||||
continue;
|
||||
}
|
||||
return fatal("poll failed");
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
r = receive_packet(s, &reply);
|
||||
if (r < 0) {
|
||||
if (errno != 0) {
|
||||
printf("receive_packet failed (%d): %s", r, strerror(errno));
|
||||
if (errno == ENETDOWN || errno == ENXIO) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#if VERBOSE > 1
|
||||
dump_dhcp_msg(&reply, r);
|
||||
#endif
|
||||
decode_dhcp_msg(&reply, r, &info);
|
||||
|
||||
if (state == STATE_SELECTING) {
|
||||
valid_reply = is_valid_reply(&discover_msg, &reply, r);
|
||||
} else {
|
||||
valid_reply = is_valid_reply(&request_msg, &reply, r);
|
||||
}
|
||||
if (!valid_reply) {
|
||||
printerr("invalid reply\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose) dump_dhcp_info(&info);
|
||||
|
||||
switch(state) {
|
||||
case STATE_SELECTING:
|
||||
if (info.type == DHCPOFFER) {
|
||||
state = STATE_REQUESTING;
|
||||
timeout = TIMEOUT_INITIAL;
|
||||
xid++;
|
||||
goto transmit;
|
||||
}
|
||||
break;
|
||||
case STATE_REQUESTING:
|
||||
if (info.type == DHCPACK) {
|
||||
printerr("configuring %s\n", ifname);
|
||||
close(s);
|
||||
return dhcp_configure(ifname, &info);
|
||||
} else if (info.type == DHCPNAK) {
|
||||
printerr("configuration request denied\n");
|
||||
close(s);
|
||||
return -1;
|
||||
} else {
|
||||
printerr("ignoring %s message in state %d\n",
|
||||
dhcp_type_to_name(info.type), state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_dhcp(char *iname)
|
||||
{
|
||||
if (if_set_addr_v4(iname, 0, 32)) {
|
||||
printerr("failed to set ip addr for %s to 0.0.0.0: %s\n", iname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (if_link_up(iname)) {
|
||||
printerr("failed to bring up interface %s: %s\n", iname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dhcp_init_ifc(iname);
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dhcpmsg.h"
|
||||
|
||||
static void *init_dhcp_msg(dhcp_msg *msg, int type, void *hwaddr, uint32_t xid)
|
||||
{
|
||||
uint8_t *x;
|
||||
|
||||
memset(msg, 0, sizeof(dhcp_msg));
|
||||
|
||||
msg->op = OP_BOOTREQUEST;
|
||||
msg->htype = HTYPE_ETHER;
|
||||
msg->hlen = 6;
|
||||
msg->hops = 0;
|
||||
|
||||
msg->flags = htons(FLAGS_BROADCAST);
|
||||
|
||||
msg->xid = xid;
|
||||
|
||||
memcpy(msg->chaddr, hwaddr, 6);
|
||||
|
||||
x = msg->options;
|
||||
|
||||
*x++ = OPT_COOKIE1;
|
||||
*x++ = OPT_COOKIE2;
|
||||
*x++ = OPT_COOKIE3;
|
||||
*x++ = OPT_COOKIE4;
|
||||
|
||||
*x++ = OPT_MESSAGE_TYPE;
|
||||
*x++ = 1;
|
||||
*x++ = type;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid)
|
||||
{
|
||||
uint8_t *x;
|
||||
|
||||
x = init_dhcp_msg(msg, DHCPDISCOVER, hwaddr, xid);
|
||||
|
||||
*x++ = OPT_PARAMETER_LIST;
|
||||
*x++ = 4;
|
||||
*x++ = OPT_SUBNET_MASK;
|
||||
*x++ = OPT_GATEWAY;
|
||||
*x++ = OPT_DNS;
|
||||
*x++ = OPT_BROADCAST_ADDR;
|
||||
|
||||
*x++ = OPT_END;
|
||||
|
||||
return DHCP_MSG_FIXED_SIZE + (x - msg->options);
|
||||
}
|
||||
|
||||
int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid,
|
||||
uint32_t ipaddr, uint32_t serveraddr)
|
||||
{
|
||||
uint8_t *x;
|
||||
|
||||
x = init_dhcp_msg(msg, DHCPREQUEST, hwaddr, xid);
|
||||
|
||||
*x++ = OPT_PARAMETER_LIST;
|
||||
*x++ = 4;
|
||||
*x++ = OPT_SUBNET_MASK;
|
||||
*x++ = OPT_GATEWAY;
|
||||
*x++ = OPT_DNS;
|
||||
*x++ = OPT_BROADCAST_ADDR;
|
||||
|
||||
*x++ = OPT_REQUESTED_IP;
|
||||
*x++ = 4;
|
||||
memcpy(x, &ipaddr, 4);
|
||||
x += 4;
|
||||
|
||||
*x++ = OPT_SERVER_ID;
|
||||
*x++ = 4;
|
||||
memcpy(x, &serveraddr, 4);
|
||||
x += 4;
|
||||
|
||||
*x++ = OPT_END;
|
||||
|
||||
return DHCP_MSG_FIXED_SIZE + (x - msg->options);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WIFI_DHCP_H_
|
||||
#define _WIFI_DHCP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PORT_BOOTP_SERVER 67
|
||||
#define PORT_BOOTP_CLIENT 68
|
||||
|
||||
/* RFC 2131 p 9 */
|
||||
typedef struct dhcp_msg dhcp_msg;
|
||||
|
||||
#define OP_BOOTREQUEST 1
|
||||
#define OP_BOOTREPLY 2
|
||||
|
||||
#define FLAGS_BROADCAST 0x8000
|
||||
|
||||
#define HTYPE_ETHER 1
|
||||
|
||||
struct dhcp_msg
|
||||
{
|
||||
uint8_t op; /* BOOTREQUEST / BOOTREPLY */
|
||||
uint8_t htype; /* hw addr type */
|
||||
uint8_t hlen; /* hw addr len */
|
||||
uint8_t hops; /* client set to 0 */
|
||||
|
||||
uint32_t xid; /* transaction id */
|
||||
|
||||
uint16_t secs; /* seconds since start of acq */
|
||||
uint16_t flags;
|
||||
|
||||
uint32_t ciaddr; /* client IP addr */
|
||||
uint32_t yiaddr; /* your (client) IP addr */
|
||||
uint32_t siaddr; /* ip addr of next server */
|
||||
/* (DHCPOFFER and DHCPACK) */
|
||||
uint32_t giaddr; /* relay agent IP addr */
|
||||
|
||||
uint8_t chaddr[16]; /* client hw addr */
|
||||
char sname[64]; /* asciiz server hostname */
|
||||
char file[128]; /* asciiz boot file name */
|
||||
|
||||
uint8_t options[1024]; /* optional parameters */
|
||||
};
|
||||
|
||||
#define DHCP_MSG_FIXED_SIZE 236
|
||||
|
||||
/* first four bytes of options are a cookie to indicate that
|
||||
** the payload are DHCP options as opposed to some other BOOTP
|
||||
** extension.
|
||||
*/
|
||||
#define OPT_COOKIE1 0x63
|
||||
#define OPT_COOKIE2 0x82
|
||||
#define OPT_COOKIE3 0x53
|
||||
#define OPT_COOKIE4 0x63
|
||||
|
||||
/* BOOTP/DHCP options - see RFC 2132 */
|
||||
#define OPT_PAD 0
|
||||
|
||||
#define OPT_SUBNET_MASK 1 /* 4 <ipaddr> */
|
||||
#define OPT_TIME_OFFSET 2 /* 4 <seconds> */
|
||||
#define OPT_GATEWAY 3 /* 4*n <ipaddr> * n */
|
||||
#define OPT_DNS 6 /* 4*n <ipaddr> * n */
|
||||
#define OPT_DOMAIN_NAME 15 /* n <domainnamestring> */
|
||||
#define OPT_BROADCAST_ADDR 28 /* 4 <ipaddr> */
|
||||
|
||||
#define OPT_REQUESTED_IP 50 /* 4 <ipaddr> */
|
||||
#define OPT_LEASE_TIME 51 /* 4 <seconds> */
|
||||
#define OPT_MESSAGE_TYPE 53 /* 1 <msgtype> */
|
||||
#define OPT_SERVER_ID 54 /* 4 <ipaddr> */
|
||||
#define OPT_PARAMETER_LIST 55 /* n <optcode> * n */
|
||||
#define OPT_MESSAGE 56 /* n <errorstring> */
|
||||
#define OPT_CLASS_ID 60 /* n <opaque> */
|
||||
#define OPT_CLIENT_ID 61 /* n <opaque> */
|
||||
#define OPT_END 255
|
||||
|
||||
/* DHCP message types */
|
||||
#define DHCPDISCOVER 1
|
||||
#define DHCPOFFER 2
|
||||
#define DHCPREQUEST 3
|
||||
#define DHCPDECLINE 4
|
||||
#define DHCPACK 5
|
||||
#define DHCPNAK 6
|
||||
#define DHCPRELEASE 7
|
||||
#define DHCPINFORM 8
|
||||
|
||||
int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid);
|
||||
|
||||
int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid,
|
||||
uint32_t ipaddr, uint32_t serveraddr);
|
||||
|
||||
#endif
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dhcpmsg.h"
|
||||
|
||||
int fatal();
|
||||
|
||||
int open_raw_socket(const char *ifname __attribute__((unused)), uint8_t *hwaddr, int if_index)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_ll bindaddr;
|
||||
|
||||
if((s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
|
||||
return fatal("socket(PF_PACKET)");
|
||||
}
|
||||
|
||||
memset(&bindaddr, 0, sizeof(bindaddr));
|
||||
bindaddr.sll_family = AF_PACKET;
|
||||
bindaddr.sll_protocol = htons(ETH_P_IP);
|
||||
bindaddr.sll_halen = ETH_ALEN;
|
||||
memcpy(bindaddr.sll_addr, hwaddr, ETH_ALEN);
|
||||
bindaddr.sll_ifindex = if_index;
|
||||
|
||||
if (bind(s, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
|
||||
return fatal("Cannot bind raw socket to interface");
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint32_t checksum(void *buffer, unsigned int count, uint32_t startsum)
|
||||
{
|
||||
uint16_t *up = (uint16_t *)buffer;
|
||||
uint32_t sum = startsum;
|
||||
uint32_t upper16;
|
||||
|
||||
while (count > 1) {
|
||||
sum += *up++;
|
||||
count -= 2;
|
||||
}
|
||||
if (count > 0) {
|
||||
sum += (uint16_t) *(uint8_t *)up;
|
||||
}
|
||||
while ((upper16 = (sum >> 16)) != 0) {
|
||||
sum = (sum & 0xffff) + upper16;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t finish_sum(uint32_t sum)
|
||||
{
|
||||
return ~sum & 0xffff;
|
||||
}
|
||||
|
||||
int send_packet(int s, int if_index, struct dhcp_msg *msg, int size,
|
||||
uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport)
|
||||
{
|
||||
struct iphdr ip;
|
||||
struct udphdr udp;
|
||||
struct iovec iov[3];
|
||||
uint32_t udpsum;
|
||||
uint16_t temp;
|
||||
struct msghdr msghdr;
|
||||
struct sockaddr_ll destaddr;
|
||||
|
||||
ip.version = IPVERSION;
|
||||
ip.ihl = sizeof(ip) >> 2;
|
||||
ip.tos = 0;
|
||||
ip.tot_len = htons(sizeof(ip) + sizeof(udp) + size);
|
||||
ip.id = 0;
|
||||
ip.frag_off = 0;
|
||||
ip.ttl = IPDEFTTL;
|
||||
ip.protocol = IPPROTO_UDP;
|
||||
ip.check = 0;
|
||||
ip.saddr = saddr;
|
||||
ip.daddr = daddr;
|
||||
ip.check = finish_sum(checksum(&ip, sizeof(ip), 0));
|
||||
|
||||
udp.source = htons(sport);
|
||||
udp.dest = htons(dport);
|
||||
udp.len = htons(sizeof(udp) + size);
|
||||
udp.check = 0;
|
||||
|
||||
/* Calculate checksum for pseudo header */
|
||||
udpsum = checksum(&ip.saddr, sizeof(ip.saddr), 0);
|
||||
udpsum = checksum(&ip.daddr, sizeof(ip.daddr), udpsum);
|
||||
temp = htons(IPPROTO_UDP);
|
||||
udpsum = checksum(&temp, sizeof(temp), udpsum);
|
||||
temp = udp.len;
|
||||
udpsum = checksum(&temp, sizeof(temp), udpsum);
|
||||
|
||||
/* Add in the checksum for the udp header */
|
||||
udpsum = checksum(&udp, sizeof(udp), udpsum);
|
||||
|
||||
/* Add in the checksum for the data */
|
||||
udpsum = checksum(msg, size, udpsum);
|
||||
udp.check = finish_sum(udpsum);
|
||||
|
||||
iov[0].iov_base = (char *)&ip;
|
||||
iov[0].iov_len = sizeof(ip);
|
||||
iov[1].iov_base = (char *)&udp;
|
||||
iov[1].iov_len = sizeof(udp);
|
||||
iov[2].iov_base = (char *)msg;
|
||||
iov[2].iov_len = size;
|
||||
memset(&destaddr, 0, sizeof(destaddr));
|
||||
destaddr.sll_family = AF_PACKET;
|
||||
destaddr.sll_protocol = htons(ETH_P_IP);
|
||||
destaddr.sll_ifindex = if_index;
|
||||
destaddr.sll_halen = ETH_ALEN;
|
||||
memcpy(destaddr.sll_addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN);
|
||||
|
||||
msghdr.msg_name = &destaddr;
|
||||
msghdr.msg_namelen = sizeof(destaddr);
|
||||
msghdr.msg_iov = iov;
|
||||
msghdr.msg_iovlen = sizeof(iov) / sizeof(struct iovec);
|
||||
msghdr.msg_flags = 0;
|
||||
msghdr.msg_control = 0;
|
||||
msghdr.msg_controllen = 0;
|
||||
return sendmsg(s, &msghdr, 0);
|
||||
}
|
||||
|
||||
int receive_packet(int s, struct dhcp_msg *msg)
|
||||
{
|
||||
int nread;
|
||||
int is_valid;
|
||||
struct dhcp_packet {
|
||||
struct iphdr ip;
|
||||
struct udphdr udp;
|
||||
struct dhcp_msg dhcp;
|
||||
} packet;
|
||||
int dhcp_size;
|
||||
uint32_t sum;
|
||||
uint16_t temp;
|
||||
uint32_t saddr, daddr;
|
||||
|
||||
nread = read(s, &packet, sizeof(packet));
|
||||
if (nread < 0) {
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* The raw packet interface gives us all packets received by the
|
||||
* network interface. We need to filter out all packets that are
|
||||
* not meant for us.
|
||||
*/
|
||||
is_valid = 0;
|
||||
if (nread < (int)(sizeof(struct iphdr) + sizeof(struct udphdr))) {
|
||||
#if VERBOSE
|
||||
ALOGD("Packet is too small (%d) to be a UDP datagram", nread);
|
||||
#endif
|
||||
} else if (packet.ip.version != IPVERSION || packet.ip.ihl != (sizeof(packet.ip) >> 2)) {
|
||||
#if VERBOSE
|
||||
ALOGD("Not a valid IP packet");
|
||||
#endif
|
||||
} else if (nread < ntohs(packet.ip.tot_len)) {
|
||||
#if VERBOSE
|
||||
ALOGD("Packet was truncated (read %d, needed %d)", nread, ntohs(packet.ip.tot_len));
|
||||
#endif
|
||||
} else if (packet.ip.protocol != IPPROTO_UDP) {
|
||||
#if VERBOSE
|
||||
ALOGD("IP protocol (%d) is not UDP", packet.ip.protocol);
|
||||
#endif
|
||||
} else if (packet.udp.dest != htons(PORT_BOOTP_CLIENT)) {
|
||||
#if VERBOSE
|
||||
ALOGD("UDP dest port (%d) is not DHCP client", ntohs(packet.udp.dest));
|
||||
#endif
|
||||
} else {
|
||||
is_valid = 1;
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Seems like it's probably a valid DHCP packet */
|
||||
/* validate IP header checksum */
|
||||
sum = finish_sum(checksum(&packet.ip, sizeof(packet.ip), 0));
|
||||
if (sum != 0) {
|
||||
printf("IP header checksum failure (0x%x)\n", packet.ip.check);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Validate the UDP checksum.
|
||||
* Since we don't need the IP header anymore, we "borrow" it
|
||||
* to construct the pseudo header used in the checksum calculation.
|
||||
*/
|
||||
dhcp_size = ntohs(packet.udp.len) - sizeof(packet.udp);
|
||||
/*
|
||||
* check validity of dhcp_size.
|
||||
* 1) cannot be negative or zero.
|
||||
* 2) src buffer contains enough bytes to copy
|
||||
* 3) cannot exceed destination buffer
|
||||
*/
|
||||
if ((dhcp_size <= 0) ||
|
||||
((int)(nread - sizeof(struct iphdr) - sizeof(struct udphdr)) < dhcp_size) ||
|
||||
((int)sizeof(struct dhcp_msg) < dhcp_size)) {
|
||||
#if VERBOSE
|
||||
printf("Malformed Packet\n");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
saddr = packet.ip.saddr;
|
||||
daddr = packet.ip.daddr;
|
||||
nread = ntohs(packet.ip.tot_len);
|
||||
memset(&packet.ip, 0, sizeof(packet.ip));
|
||||
packet.ip.saddr = saddr;
|
||||
packet.ip.daddr = daddr;
|
||||
packet.ip.protocol = IPPROTO_UDP;
|
||||
packet.ip.tot_len = packet.udp.len;
|
||||
temp = packet.udp.check;
|
||||
packet.udp.check = 0;
|
||||
sum = finish_sum(checksum(&packet, nread, 0));
|
||||
packet.udp.check = temp;
|
||||
if (!sum)
|
||||
sum = finish_sum(sum);
|
||||
if (temp != sum) {
|
||||
printf("UDP header checksum failure (0x%x should be 0x%x)\n", sum, temp);
|
||||
return -1;
|
||||
}
|
||||
memcpy(msg, &packet.dhcp, dhcp_size);
|
||||
return dhcp_size;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _WIFI_PACKET_H_
|
||||
#define _WIFI_PACKET_H_
|
||||
|
||||
int open_raw_socket(const char *ifname, uint8_t *hwaddr, int if_index);
|
||||
int send_packet(int s, int if_index, struct dhcp_msg *msg, int size,
|
||||
uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport);
|
||||
int receive_packet(int s, struct dhcp_msg *msg);
|
||||
|
||||
#endif
|
||||
@@ -1,748 +0,0 @@
|
||||
/* This example is placed in the public domain. */
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#include <net/if.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
//#include <linux/if.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
#include "ifutils.h"
|
||||
|
||||
#define ERRMSG(v...) printf("%s-%d: error=%s %s\n", __func__, __LINE__, strerror(errno), ##v)
|
||||
extern void dbg_time(const char *fmt, ...);
|
||||
int mask_to_prefix_v4(uint32_t mask)
|
||||
{
|
||||
int ret = 0;
|
||||
while (mask)
|
||||
{
|
||||
mask = mask & (mask - 1);
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *ipaddr_to_string_v4(in_addr_t ipaddr)
|
||||
{
|
||||
static char buf[INET6_ADDRSTRLEN] = {'\0'};
|
||||
buf[0] = '\0';
|
||||
uint32_t addr = ipaddr;
|
||||
return inet_ntop(AF_INET, &addr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
const char *ipaddr_to_string_v6(uint8_t *ipaddr)
|
||||
{
|
||||
static char buf[INET6_ADDRSTRLEN] = {'\0'};
|
||||
buf[0] = '\0';
|
||||
return inet_ntop(AF_INET6, ipaddr, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static void ifc_init_ifr(const char *name, struct ifreq *ifr)
|
||||
{
|
||||
memset(ifr, 0, sizeof(struct ifreq));
|
||||
strncpy(ifr->ifr_name, name, IFNAMSIZ);
|
||||
ifr->ifr_name[IFNAMSIZ - 1] = 0;
|
||||
}
|
||||
|
||||
int if_get_hwaddr(const char *name, void *ptr)
|
||||
{
|
||||
int r;
|
||||
struct ifreq ifr;
|
||||
ifc_init_ifr(name, &ifr);
|
||||
|
||||
int ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (ifc_ctl_sock < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
|
||||
if (r < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int if_act_on_link(const char *ifname, int state)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifinfomsg *ifm;
|
||||
int ret;
|
||||
unsigned int seq, portid, change = 0, flags = 0;
|
||||
static int oldstate = -1;
|
||||
|
||||
if (state == oldstate)
|
||||
return 0;
|
||||
oldstate = state;
|
||||
|
||||
if (state)
|
||||
{
|
||||
change |= IFF_UP;
|
||||
flags |= IFF_UP;
|
||||
}
|
||||
else
|
||||
{
|
||||
change |= IFF_UP;
|
||||
flags &= ~IFF_UP;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = RTM_NEWLINK;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
|
||||
ifm->ifi_family = AF_UNSPEC;
|
||||
ifm->ifi_change = change;
|
||||
ifm->ifi_flags = flags;
|
||||
|
||||
mnl_attr_put_str(nlh, IFLA_IFNAME, ifname);
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG("mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_link_up(const char *ifname)
|
||||
{
|
||||
dbg_time("if_link_up %s",ifname);
|
||||
return if_act_on_link(ifname, 1);
|
||||
}
|
||||
|
||||
int if_link_down(const char *ifname)
|
||||
{
|
||||
|
||||
dbg_time("if_link_down %s",ifname);
|
||||
return if_act_on_link(ifname, 0);
|
||||
}
|
||||
|
||||
int if_set_mtu(const char *ifname, uint32_t mtu)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
unsigned int seq, portid;
|
||||
struct mnl_socket *nl;
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifinfomsg *ifm;
|
||||
int ret;
|
||||
int iface;
|
||||
static uint32_t oldmtu = 1500;
|
||||
|
||||
if (mtu == oldmtu)
|
||||
return 0;
|
||||
oldmtu = mtu;
|
||||
|
||||
iface = if_nametoindex(ifname);
|
||||
if (iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = RTM_NEWLINK;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifinfomsg));
|
||||
ifm->ifi_family = AF_UNSPEC;
|
||||
ifm->ifi_index = iface;
|
||||
ifm->ifi_change = 0xFFFFFFFF;
|
||||
ifm->ifi_type = 0;
|
||||
ifm->ifi_flags = IFF_NOARP | IFF_MULTICAST;
|
||||
|
||||
mnl_attr_put_u32(nlh, IFLA_MTU, mtu);
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the ip addr object
|
||||
*
|
||||
* @param operate
|
||||
* 0 -> add address on interface
|
||||
* 1 -> delete address on interface
|
||||
* @param ifname
|
||||
* @param ipaddr
|
||||
* @param prefix
|
||||
* @return int
|
||||
*/
|
||||
static int if_act_on_addr(bool operate, int proto, const char *ifname, addr_t *ipaddr, uint32_t prefix)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifaddrmsg *ifm;
|
||||
uint32_t seq, portid;
|
||||
int ret, family = proto;
|
||||
|
||||
int iface;
|
||||
|
||||
iface = if_nametoindex(ifname);
|
||||
if (iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
if (operate)
|
||||
nlh->nlmsg_type = RTM_NEWADDR;
|
||||
else
|
||||
nlh->nlmsg_type = RTM_DELADDR;
|
||||
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
|
||||
ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifaddrmsg));
|
||||
|
||||
ifm->ifa_family = family;
|
||||
ifm->ifa_prefixlen = prefix;
|
||||
ifm->ifa_flags = IFA_F_PERMANENT;
|
||||
|
||||
ifm->ifa_scope = RT_SCOPE_UNIVERSE;
|
||||
ifm->ifa_index = iface;
|
||||
|
||||
/*
|
||||
* The exact meaning of IFA_LOCAL and IFA_ADDRESS depend
|
||||
* on the address family being used and the device type.
|
||||
* For broadcast devices (like the interfaces we use),
|
||||
* for IPv4 we specify both and they are used interchangeably.
|
||||
* For IPv6, only IFA_ADDRESS needs to be set.
|
||||
*/
|
||||
if (family == AF_INET)
|
||||
{
|
||||
mnl_attr_put_u32(nlh, IFA_LOCAL, ipaddr->ip);
|
||||
mnl_attr_put_u32(nlh, IFA_ADDRESS, ipaddr->ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
mnl_attr_put(nlh, IFA_ADDRESS, sizeof(struct in6_addr), ipaddr);
|
||||
}
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_set_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
addr.ip = ipaddr;
|
||||
return if_act_on_addr(1, AF_INET, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
int if_del_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
addr.ip = ipaddr;
|
||||
return if_act_on_addr(0, AF_INET, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
int if_set_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
memcpy(&addr.ip6, ipaddr, 16);
|
||||
return if_act_on_addr(1, AF_INET6, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
int if_del_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix)
|
||||
{
|
||||
addr_t addr;
|
||||
memcpy(&addr.ip6, ipaddr, 16);
|
||||
return if_act_on_addr(0, AF_INET6, ifname, &addr, prefix);
|
||||
}
|
||||
|
||||
static int data_attr_cb(const struct nlattr *attr, void *data)
|
||||
{
|
||||
const struct nlattr **tb = data;
|
||||
int type = mnl_attr_get_type(attr);
|
||||
|
||||
/* skip unsupported attribute in user-space */
|
||||
if (mnl_attr_type_valid(attr, IFA_MAX) < 0)
|
||||
return MNL_CB_OK;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_attr_validate");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tb[type] = attr;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int data_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[IFA_MAX + 1] = {};
|
||||
struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh);
|
||||
struct addrinfo_t *addrinfo = (struct addrinfo_t *)data;
|
||||
void *addr = NULL;
|
||||
|
||||
mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb);
|
||||
if (tb[IFA_ADDRESS])
|
||||
{
|
||||
char out[INET6_ADDRSTRLEN];
|
||||
|
||||
addr = mnl_attr_get_payload(tb[IFLA_ADDRESS]);
|
||||
addr = mnl_attr_get_payload(tb[IFA_ADDRESS]);
|
||||
if (!inet_ntop(ifa->ifa_family, addr, out, sizeof(out)))
|
||||
ERRMSG("inet_ntop");
|
||||
// printf("%d %d-> %d %s\n", addrinfo->iface, ifa->ifa_index, ifa->ifa_scope, out);
|
||||
|
||||
addrinfo->addrs[addrinfo->num].prefix = ifa->ifa_prefixlen;
|
||||
if (ifa->ifa_index == addrinfo->iface)
|
||||
{
|
||||
if (ifa->ifa_family == AF_INET6)
|
||||
memcpy(addrinfo->addrs[addrinfo->num].address.ip6.s6_addr, addr, 16);
|
||||
if (ifa->ifa_family == AF_INET)
|
||||
memcpy(&(addrinfo->addrs[addrinfo->num].address.ip), addr, 4);
|
||||
addrinfo->num++;
|
||||
}
|
||||
}
|
||||
|
||||
// ifa->ifa_scope
|
||||
// 0: global
|
||||
// 200: site
|
||||
// 253: link
|
||||
// 254: host
|
||||
// 255: nowhere
|
||||
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param ifname
|
||||
* @param proto
|
||||
* AF_INET -> for IPv4
|
||||
* AF_INET6 -> for IPv6
|
||||
* @return int
|
||||
*/
|
||||
static int if_get_addr(const char *ifname, int proto, struct addrinfo_t *addrinfo)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
unsigned int seq, portid;
|
||||
struct mnl_socket *nl;
|
||||
struct nlmsghdr *nlh;
|
||||
struct rtgenmsg *rt;
|
||||
int ret;
|
||||
|
||||
addrinfo->iface = if_nametoindex(ifname);
|
||||
if (addrinfo->iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
nlh->nlmsg_type = RTM_GETADDR;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
|
||||
if (proto == AF_INET)
|
||||
rt->rtgen_family = AF_INET;
|
||||
else if (proto == AF_INET6)
|
||||
rt->rtgen_family = AF_INET6;
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
while (ret > 0)
|
||||
{
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, data_cb, addrinfo);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
}
|
||||
if (ret == -1)
|
||||
{
|
||||
ERRMSG(" error");
|
||||
return -1;
|
||||
}
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_flush_v4_addr(const char *ifname)
|
||||
{
|
||||
struct addrinfo_t addrinfo;
|
||||
int i = 0;
|
||||
|
||||
memset(&addrinfo, 0, sizeof(struct addrinfo_t));
|
||||
if_get_addr(ifname, AF_INET, &addrinfo);
|
||||
for (; i < addrinfo.num; i++)
|
||||
{
|
||||
// printf("remove address: %s\n", ipaddr_to_string_v4(addrinfo.addrs[i].address.ip));
|
||||
if_del_addr_v4(ifname, addrinfo.addrs[i].address.ip, addrinfo.addrs[i].prefix);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_flush_v6_addr(const char *ifname)
|
||||
{
|
||||
struct addrinfo_t addrinfo;
|
||||
int i = 0;
|
||||
|
||||
memset(&addrinfo, 0, sizeof(struct addrinfo_t));
|
||||
if_get_addr(ifname, AF_INET6, &addrinfo);
|
||||
for (; i < addrinfo.num; i++)
|
||||
{
|
||||
// printf("remove address: %s\n", ipaddr_to_string_v6(addrinfo.addrs[i].address.ip6.s6_addr));
|
||||
if_del_addr_v6(ifname, addrinfo.addrs[i].address.ip6.s6_addr, addrinfo.addrs[i].prefix);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the route addr object
|
||||
* Usage:
|
||||
* iface destination cidr [gateway]
|
||||
* Example:
|
||||
* eth0 10.0.1.12 32 10.0.1.11
|
||||
* eth0 ffff::10.0.1.12 128 fdff::1
|
||||
* @param operate
|
||||
* add or del
|
||||
* @param ifname
|
||||
* @param dstaddr
|
||||
* @param prefix
|
||||
* @param gwaddr
|
||||
* @return int
|
||||
*/
|
||||
int if_act_on_route(bool operate, int proto, const char *ifname, addr_t *dstaddr, uint32_t prefix, addr_t *gwaddr)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
struct rtmsg *rtm;
|
||||
uint32_t seq, portid;
|
||||
int iface, ret, family = proto;
|
||||
|
||||
iface = if_nametoindex(ifname);
|
||||
if (iface == 0)
|
||||
{
|
||||
ERRMSG(" if_nametoindex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buf);
|
||||
if (operate)
|
||||
nlh->nlmsg_type = RTM_NEWROUTE;
|
||||
else
|
||||
nlh->nlmsg_type = RTM_DELROUTE;
|
||||
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
|
||||
nlh->nlmsg_seq = seq = time(NULL);
|
||||
|
||||
rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
|
||||
rtm->rtm_family = family;
|
||||
rtm->rtm_dst_len = prefix;
|
||||
rtm->rtm_src_len = 0;
|
||||
rtm->rtm_tos = 0;
|
||||
rtm->rtm_protocol = RTPROT_STATIC;
|
||||
rtm->rtm_table = RT_TABLE_MAIN;
|
||||
rtm->rtm_type = RTN_UNICAST;
|
||||
/* is there any gateway? */
|
||||
rtm->rtm_scope = gwaddr ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
|
||||
rtm->rtm_flags = 0;
|
||||
|
||||
if (family == AF_INET)
|
||||
mnl_attr_put_u32(nlh, RTA_DST, dstaddr->ip);
|
||||
else
|
||||
mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), dstaddr);
|
||||
|
||||
mnl_attr_put_u32(nlh, RTA_OIF, iface);
|
||||
if (gwaddr)
|
||||
{
|
||||
if (family == AF_INET)
|
||||
mnl_attr_put_u32(nlh, RTA_GATEWAY, gwaddr->ip);
|
||||
else
|
||||
{
|
||||
mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr), gwaddr);
|
||||
}
|
||||
}
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (nl == NULL)
|
||||
{
|
||||
ERRMSG(" mnl_socket_open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_bind");
|
||||
return -1;
|
||||
}
|
||||
portid = mnl_socket_get_portid(nl);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_sendto");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_socket_recvfrom");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" mnl_cb_run");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnl_socket_close(nl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_set_default_route_v4(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
int if_del_default_route_v4(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
int if_set_default_route_v6(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
int if_del_default_route_v6(const char *ifname)
|
||||
{
|
||||
return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the default gwaddr object
|
||||
* set default gw
|
||||
* @param operate
|
||||
* @param ifname
|
||||
* @param gwaddr
|
||||
* gateway ip
|
||||
* @return int
|
||||
*/
|
||||
int if_set_route_gw_v4(const char *ifname, in_addr_t gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
addr.ip = gwaddr;
|
||||
return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_del_route_gw_v4(const char *ifname, in_addr_t gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
addr.ip = gwaddr;
|
||||
return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_set_route_gw_v6(const char *ifname, uint8_t *gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
memcpy(&addr.ip6, gwaddr, 16);
|
||||
return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_del_route_gw_v6(const char *ifname, uint8_t *gwaddr)
|
||||
{
|
||||
addr_t addr;
|
||||
memset(&addr, 0, sizeof(addr_t));
|
||||
memcpy(&addr.ip6, gwaddr, 16);
|
||||
return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr);
|
||||
}
|
||||
|
||||
int if_set_dns(const char *dns1, const char *dns2)
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[128] = {'\0'};
|
||||
int fd = open("/etc/resolv.conf", O_CREAT | O_WRONLY | O_TRUNC);
|
||||
if (fd < 0)
|
||||
{
|
||||
ERRMSG(" fail to open /etc/resolv.conf");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dns1)
|
||||
snprintf(buf, sizeof(buf), "nameserver %s\n", dns1);
|
||||
if (dns2)
|
||||
snprintf(buf, sizeof(buf), "nameserver %s\n", dns2);
|
||||
ret = write(fd, buf, strlen(buf));
|
||||
if (ret < 0)
|
||||
{
|
||||
ERRMSG(" write dns");
|
||||
}
|
||||
close(fd);
|
||||
return ret > 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int if_set_network_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix,
|
||||
in_addr_t gwaddr, in_addr_t dns1, in_addr_t dns2)
|
||||
{
|
||||
if_link_up(ifname);
|
||||
sleep(2);
|
||||
if_set_addr_v4(ifname, ipaddr, prefix);
|
||||
if_set_default_route_v4(ifname);
|
||||
if_set_dns(ipaddr_to_string_v4(dns1), ipaddr_to_string_v4(dns2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int if_set_network_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix,
|
||||
uint8_t *gwaddr, uint8_t *dns1, uint8_t *dns2)
|
||||
{
|
||||
if_link_up(ifname);
|
||||
sleep(2);
|
||||
if_set_addr_v6(ifname, ipaddr, prefix);
|
||||
if_set_default_route_v6(ifname);
|
||||
if_set_dns(ipaddr_to_string_v6(dns1), ipaddr_to_string_v6(dns2));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
#ifndef __IFUTILS_H__
|
||||
#define __IFUTILS_H__
|
||||
|
||||
typedef union {
|
||||
in_addr_t ip;
|
||||
struct in6_addr ip6;
|
||||
} addr_t;
|
||||
|
||||
#define MAX_IP_NUM 32
|
||||
struct addrinfo_t
|
||||
{
|
||||
int iface;
|
||||
int num;
|
||||
struct
|
||||
{
|
||||
int prefix;
|
||||
addr_t address;
|
||||
} addrs[MAX_IP_NUM];
|
||||
};
|
||||
|
||||
const char *ipaddr_to_string_v4(in_addr_t ipaddr);
|
||||
const char *ipaddr_to_string_v6(uint8_t *ipaddr);
|
||||
int mask_to_prefix_v4(in_addr_t mask);
|
||||
|
||||
int if_get_hwaddr(const char *name, void *ptr);
|
||||
|
||||
int if_link_down(const char *ifname);
|
||||
int if_link_up(const char *ifname);
|
||||
int if_set_mtu(const char *ifname, uint32_t mtu);
|
||||
|
||||
int if_set_addr_v4(const char *name, in_addr_t address, uint32_t prefixlen);
|
||||
int if_del_addr_v4(const char *name, in_addr_t address, uint32_t prefixlen);
|
||||
int if_set_addr_v6(const char *name, uint8_t *address, uint32_t prefixlen);
|
||||
int if_del_addr_v6(const char *name, uint8_t *address, uint32_t prefixlen);
|
||||
int if_flush_v4_addr(const char *ifname);
|
||||
int if_flush_v6_addr(const char *ifname);
|
||||
|
||||
int if_set_route_gw_v4(const char *ifname, in_addr_t gwaddr);
|
||||
int if_del_route_gw_v4(const char *ifname, in_addr_t gwaddr);
|
||||
int if_set_default_route_v4(const char *ifname);
|
||||
int if_del_default_route_v4(const char *ifname);
|
||||
|
||||
int if_set_route_gw_v6(const char *ifname, uint8_t *gwaddr);
|
||||
int if_del_route_gw_v6(const char *ifname, uint8_t *gwaddr);
|
||||
int if_set_default_route_v6(const char *ifname);
|
||||
int if_del_default_route_v6(const char *ifname);
|
||||
|
||||
int if_set_network_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix,
|
||||
in_addr_t gwaddr, in_addr_t dns1, in_addr_t dns2);
|
||||
int if_set_network_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix,
|
||||
uint8_t *gwaddr, uint8_t *dns1, uint8_t *dns2);
|
||||
|
||||
#endif //__IFUTILS_H__
|
||||
@@ -1,202 +0,0 @@
|
||||
#ifndef _LIBMNL_H_
|
||||
#define _LIBMNL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h> /* for sa_family_t */
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Netlink socket API
|
||||
*/
|
||||
|
||||
#define MNL_SOCKET_AUTOPID 0
|
||||
#define MNL_SOCKET_BUFFER_SIZE (sysconf(_SC_PAGESIZE) < 8192L ? sysconf(_SC_PAGESIZE) : 8192L)
|
||||
#define MNL_SOCKET_DUMP_SIZE 32768
|
||||
|
||||
struct mnl_socket;
|
||||
|
||||
extern struct mnl_socket *mnl_socket_open(int bus);
|
||||
extern struct mnl_socket *mnl_socket_open2(int bus, int flags);
|
||||
extern struct mnl_socket *mnl_socket_fdopen(int fd);
|
||||
extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid);
|
||||
extern int mnl_socket_close(struct mnl_socket *nl);
|
||||
extern int mnl_socket_get_fd(const struct mnl_socket *nl);
|
||||
extern unsigned int mnl_socket_get_portid(const struct mnl_socket *nl);
|
||||
extern ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *req, size_t siz);
|
||||
extern ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t siz);
|
||||
extern int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t len);
|
||||
extern int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t *len);
|
||||
|
||||
/*
|
||||
* Netlink message API
|
||||
*/
|
||||
|
||||
#define MNL_ALIGNTO 4
|
||||
#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
|
||||
#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
|
||||
|
||||
extern size_t mnl_nlmsg_size(size_t len);
|
||||
extern size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh);
|
||||
|
||||
/* Netlink message header builder */
|
||||
extern struct nlmsghdr *mnl_nlmsg_put_header(void *buf);
|
||||
extern void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size);
|
||||
|
||||
/* Netlink message iterators */
|
||||
extern bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len);
|
||||
extern struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len);
|
||||
|
||||
/* Netlink sequence tracking */
|
||||
extern bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq);
|
||||
|
||||
/* Netlink portID checking */
|
||||
extern bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid);
|
||||
|
||||
/* Netlink message getters */
|
||||
extern void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh);
|
||||
extern void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset);
|
||||
extern void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh);
|
||||
|
||||
/* Netlink message printer */
|
||||
extern void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size);
|
||||
|
||||
/* Message batch helpers */
|
||||
struct mnl_nlmsg_batch;
|
||||
extern struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf, size_t bufsiz);
|
||||
extern bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b);
|
||||
extern void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b);
|
||||
extern size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b);
|
||||
extern void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b);
|
||||
extern void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b);
|
||||
extern void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b);
|
||||
extern bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b);
|
||||
|
||||
/*
|
||||
* Netlink attributes API
|
||||
*/
|
||||
#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
|
||||
|
||||
/* TLV attribute getters */
|
||||
extern uint16_t mnl_attr_get_type(const struct nlattr *attr);
|
||||
extern uint16_t mnl_attr_get_len(const struct nlattr *attr);
|
||||
extern uint16_t mnl_attr_get_payload_len(const struct nlattr *attr);
|
||||
extern void *mnl_attr_get_payload(const struct nlattr *attr);
|
||||
extern uint8_t mnl_attr_get_u8(const struct nlattr *attr);
|
||||
extern uint16_t mnl_attr_get_u16(const struct nlattr *attr);
|
||||
extern uint32_t mnl_attr_get_u32(const struct nlattr *attr);
|
||||
extern uint64_t mnl_attr_get_u64(const struct nlattr *attr);
|
||||
extern const char *mnl_attr_get_str(const struct nlattr *attr);
|
||||
|
||||
/* TLV attribute putters */
|
||||
extern void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data);
|
||||
extern void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data);
|
||||
extern void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data);
|
||||
extern void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data);
|
||||
extern void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data);
|
||||
extern void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data);
|
||||
extern void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data);
|
||||
|
||||
/* TLV attribute putters with buffer boundary checkings */
|
||||
extern bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data);
|
||||
extern bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data);
|
||||
extern bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data);
|
||||
extern bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data);
|
||||
extern bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data);
|
||||
extern bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data);
|
||||
extern bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data);
|
||||
|
||||
/* TLV attribute nesting */
|
||||
extern struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type);
|
||||
extern struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type);
|
||||
extern void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start);
|
||||
extern void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start);
|
||||
|
||||
/* TLV validation */
|
||||
extern int mnl_attr_type_valid(const struct nlattr *attr, uint16_t maxtype);
|
||||
|
||||
enum mnl_attr_data_type {
|
||||
MNL_TYPE_UNSPEC,
|
||||
MNL_TYPE_U8,
|
||||
MNL_TYPE_U16,
|
||||
MNL_TYPE_U32,
|
||||
MNL_TYPE_U64,
|
||||
MNL_TYPE_STRING,
|
||||
MNL_TYPE_FLAG,
|
||||
MNL_TYPE_MSECS,
|
||||
MNL_TYPE_NESTED,
|
||||
MNL_TYPE_NESTED_COMPAT,
|
||||
MNL_TYPE_NUL_STRING,
|
||||
MNL_TYPE_BINARY,
|
||||
MNL_TYPE_MAX,
|
||||
};
|
||||
|
||||
extern int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type);
|
||||
extern int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t len);
|
||||
|
||||
/* TLV iterators */
|
||||
extern bool mnl_attr_ok(const struct nlattr *attr, int len);
|
||||
extern struct nlattr *mnl_attr_next(const struct nlattr *attr);
|
||||
|
||||
#define mnl_attr_for_each(attr, nlh, offset) \
|
||||
for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
|
||||
mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
#define mnl_attr_for_each_nested(attr, nest) \
|
||||
for ((attr) = mnl_attr_get_payload(nest); \
|
||||
mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
#define mnl_attr_for_each_payload(payload, payload_size) \
|
||||
for ((attr) = (payload); \
|
||||
mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
/* TLV callback-based attribute parsers */
|
||||
typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
|
||||
|
||||
extern int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data);
|
||||
extern int mnl_attr_parse_nested(const struct nlattr *attr, mnl_attr_cb_t cb, void *data);
|
||||
extern int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data);
|
||||
|
||||
/*
|
||||
* callback API
|
||||
*/
|
||||
#define MNL_CB_ERROR -1
|
||||
#define MNL_CB_STOP 0
|
||||
#define MNL_CB_OK 1
|
||||
|
||||
typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data);
|
||||
|
||||
extern int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data);
|
||||
|
||||
extern int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len);
|
||||
|
||||
/*
|
||||
* other declarations
|
||||
*/
|
||||
|
||||
#ifndef SOL_NETLINK
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
#ifndef MNL_ARRAY_SIZE
|
||||
#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,556 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
/**
|
||||
* \defgroup nlmsg Netlink message helpers
|
||||
*
|
||||
* Netlink message:
|
||||
* \verbatim
|
||||
|<----------------- 4 bytes ------------------->|
|
||||
|<----- 2 bytes ------>|<------- 2 bytes ------>|
|
||||
|-----------------------------------------------|
|
||||
| Message length (including header) |
|
||||
|-----------------------------------------------|
|
||||
| Message type | Message flags |
|
||||
|-----------------------------------------------|
|
||||
| Message sequence number |
|
||||
|-----------------------------------------------|
|
||||
| Netlink PortID |
|
||||
|-----------------------------------------------|
|
||||
| |
|
||||
. Payload .
|
||||
|_______________________________________________|
|
||||
\endverbatim
|
||||
*
|
||||
* There is usually an extra header after the the Netlink header (at the
|
||||
* beginning of the payload). This extra header is specific of the Netlink
|
||||
* subsystem. After this extra header, it comes the sequence of attributes
|
||||
* that are expressed in Type-Length-Value (TLV) format.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_size - calculate the size of Netlink message (without alignment)
|
||||
* \param len length of the Netlink payload
|
||||
*
|
||||
* This function returns the size of a netlink message (header plus payload)
|
||||
* without alignment.
|
||||
*/
|
||||
size_t mnl_nlmsg_size(size_t len)
|
||||
{
|
||||
return len + MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload_len - get the length of the Netlink payload
|
||||
* \param nlh pointer to the header of the Netlink message
|
||||
*
|
||||
* This function returns the Length of the netlink payload, ie. the length
|
||||
* of the full message minus the size of the Netlink header.
|
||||
*/
|
||||
size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return nlh->nlmsg_len - MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_put_header - reserve and prepare room for Netlink header
|
||||
* \param buf memory already allocated to store the Netlink header
|
||||
*
|
||||
* This function sets to zero the room that is required to put the Netlink
|
||||
* header in the memory buffer passed as parameter. This function also
|
||||
* initializes the nlmsg_len field to the size of the Netlink header. This
|
||||
* function returns a pointer to the Netlink header structure.
|
||||
*/
|
||||
struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
|
||||
{
|
||||
int len = MNL_ALIGN(sizeof(struct nlmsghdr));
|
||||
struct nlmsghdr *nlh = buf;
|
||||
|
||||
memset(buf, 0, len);
|
||||
nlh->nlmsg_len = len;
|
||||
return nlh;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_put_extra_header - reserve and prepare room for an extra header
|
||||
* \param nlh pointer to Netlink header
|
||||
* \param size size of the extra header that we want to put
|
||||
*
|
||||
* This function sets to zero the room that is required to put the extra
|
||||
* header after the initial Netlink header. This function also increases
|
||||
* the nlmsg_len field. You have to invoke mnl_nlmsg_put_header() before
|
||||
* you call this function. This function returns a pointer to the extra
|
||||
* header.
|
||||
*/
|
||||
void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh,
|
||||
size_t size)
|
||||
{
|
||||
char *ptr = (char *)nlh + nlh->nlmsg_len;
|
||||
size_t len = MNL_ALIGN(size);
|
||||
nlh->nlmsg_len += len;
|
||||
memset(ptr, 0, len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload - get a pointer to the payload of the netlink message
|
||||
* \param nlh pointer to a netlink header
|
||||
*
|
||||
* This function returns a pointer to the payload of the netlink message.
|
||||
*/
|
||||
void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return (void *)nlh + MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload_offset - get a pointer to the payload of the message
|
||||
* \param nlh pointer to a netlink header
|
||||
* \param offset offset to the payload of the attributes TLV set
|
||||
*
|
||||
* This function returns a pointer to the payload of the netlink message plus
|
||||
* a given offset.
|
||||
*/
|
||||
void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh,
|
||||
size_t offset)
|
||||
{
|
||||
return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_ok - check a there is room for netlink message
|
||||
* \param nlh netlink message that we want to check
|
||||
* \param len remaining bytes in a buffer that contains the netlink message
|
||||
*
|
||||
* This function is used to check that a buffer that contains a netlink
|
||||
* message has enough room for the netlink message that it stores, ie. this
|
||||
* function can be used to verify that a netlink message is not malformed nor
|
||||
* truncated.
|
||||
*
|
||||
* This function does not set errno in case of error since it is intended
|
||||
* for iterations. Thus, it returns true on success and false on error.
|
||||
*
|
||||
* The len parameter may become negative in malformed messages during message
|
||||
* iteration, that is why we use a signed integer.
|
||||
*/
|
||||
bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
|
||||
{
|
||||
return len >= (int)sizeof(struct nlmsghdr) &&
|
||||
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||
(int)nlh->nlmsg_len <= len;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_next - get the next netlink message in a multipart message
|
||||
* \param nlh current netlink message that we are handling
|
||||
* \param len length of the remaining bytes in the buffer (passed by reference).
|
||||
*
|
||||
* This function returns a pointer to the next netlink message that is part
|
||||
* of a multi-part netlink message. Netlink can batch several messages into
|
||||
* one buffer so that the receiver has to iterate over the whole set of
|
||||
* Netlink messages.
|
||||
*
|
||||
* You have to use mnl_nlmsg_ok() to check if the next Netlink message is
|
||||
* valid.
|
||||
*/
|
||||
struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh,
|
||||
int *len)
|
||||
{
|
||||
*len -= MNL_ALIGN(nlh->nlmsg_len);
|
||||
return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_get_payload_tail - get the ending of the netlink message
|
||||
* \param nlh pointer to netlink message
|
||||
*
|
||||
* This function returns a pointer to the netlink message tail. This is useful
|
||||
* to build a message since we continue adding attributes at the end of the
|
||||
* message.
|
||||
*/
|
||||
void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_seq_ok - perform sequence tracking
|
||||
* \param nlh current netlink message that we are handling
|
||||
* \param seq last sequence number used to send a message
|
||||
*
|
||||
* This functions returns true if the sequence tracking is fulfilled, otherwise
|
||||
* false is returned. We skip the tracking for netlink messages whose sequence
|
||||
* number is zero since it is usually reserved for event-based kernel
|
||||
* notifications. On the other hand, if seq is set but the message sequence
|
||||
* number is not set (i.e. this is an event message coming from kernel-space),
|
||||
* then we also skip the tracking. This approach is good if we use the same
|
||||
* socket to send commands to kernel-space (that we want to track) and to
|
||||
* listen to events (that we do not track).
|
||||
*/
|
||||
bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh,
|
||||
unsigned int seq)
|
||||
{
|
||||
return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_portid_ok - perform portID origin check
|
||||
* \param nlh current netlink message that we are handling
|
||||
* \param portid netlink portid that we want to check
|
||||
*
|
||||
* This functions returns true if the origin is fulfilled, otherwise
|
||||
* false is returned. We skip the tracking for netlink message whose portID
|
||||
* is zero since it is reserved for event-based kernel notifications. On the
|
||||
* other hand, if portid is set but the message PortID is not (i.e. this
|
||||
* is an event message coming from kernel-space), then we also skip the
|
||||
* tracking. This approach is good if we use the same socket to send commands
|
||||
* to kernel-space (that we want to track) and to listen to events (that we
|
||||
* do not track).
|
||||
*/
|
||||
bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh,
|
||||
unsigned int portid)
|
||||
{
|
||||
return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
|
||||
}
|
||||
|
||||
static void mnl_nlmsg_fprintf_header(FILE *fd, const struct nlmsghdr *nlh)
|
||||
{
|
||||
fprintf(fd, "----------------\t------------------\n");
|
||||
fprintf(fd, "| %.010u |\t| message length |\n", nlh->nlmsg_len);
|
||||
fprintf(fd, "| %.05u | %c%c%c%c |\t| type | flags |\n",
|
||||
nlh->nlmsg_type,
|
||||
nlh->nlmsg_flags & NLM_F_REQUEST ? 'R' : '-',
|
||||
nlh->nlmsg_flags & NLM_F_MULTI ? 'M' : '-',
|
||||
nlh->nlmsg_flags & NLM_F_ACK ? 'A' : '-',
|
||||
nlh->nlmsg_flags & NLM_F_ECHO ? 'E' : '-');
|
||||
fprintf(fd, "| %.010u |\t| sequence number|\n", nlh->nlmsg_seq);
|
||||
fprintf(fd, "| %.010u |\t| port ID |\n", nlh->nlmsg_pid);
|
||||
fprintf(fd, "----------------\t------------------\n");
|
||||
}
|
||||
|
||||
static void mnl_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh,
|
||||
size_t extra_header_size)
|
||||
{
|
||||
int rem = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i=sizeof(struct nlmsghdr); i<nlh->nlmsg_len; i+=4) {
|
||||
char *b = (char *) nlh;
|
||||
struct nlattr *attr = (struct nlattr *) (b+i);
|
||||
|
||||
/* netlink control message. */
|
||||
if (nlh->nlmsg_type < NLMSG_MIN_TYPE) {
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| |\n");
|
||||
/* special handling for the extra header. */
|
||||
} else if (extra_header_size > 0) {
|
||||
extra_header_size -= 4;
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| extra header |\n");
|
||||
/* this seems like an attribute header. */
|
||||
} else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) {
|
||||
fprintf(fd, "|%c[%d;%dm"
|
||||
"%.5u"
|
||||
"%c[%dm"
|
||||
"|"
|
||||
"%c[%d;%dm"
|
||||
"%c%c"
|
||||
"%c[%dm"
|
||||
"|"
|
||||
"%c[%d;%dm"
|
||||
"%.5u"
|
||||
"%c[%dm|\t",
|
||||
27, 1, 31,
|
||||
attr->nla_len,
|
||||
27, 0,
|
||||
27, 1, 32,
|
||||
attr->nla_type & NLA_F_NESTED ? 'N' : '-',
|
||||
attr->nla_type &
|
||||
NLA_F_NET_BYTEORDER ? 'B' : '-',
|
||||
27, 0,
|
||||
27, 1, 34,
|
||||
attr->nla_type & NLA_TYPE_MASK,
|
||||
27, 0);
|
||||
fprintf(fd, "|len |flags| type|\n");
|
||||
|
||||
if (!(attr->nla_type & NLA_F_NESTED)) {
|
||||
rem = NLA_ALIGN(attr->nla_len) -
|
||||
sizeof(struct nlattr);
|
||||
}
|
||||
/* this is the attribute payload. */
|
||||
} else if (rem > 0) {
|
||||
rem -= 4;
|
||||
fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
|
||||
0xff & b[i], 0xff & b[i+1],
|
||||
0xff & b[i+2], 0xff & b[i+3]);
|
||||
fprintf(fd, "| data |");
|
||||
fprintf(fd, "\t %c %c %c %c\n",
|
||||
isprint(b[i]) ? b[i] : ' ',
|
||||
isprint(b[i+1]) ? b[i+1] : ' ',
|
||||
isprint(b[i+2]) ? b[i+2] : ' ',
|
||||
isprint(b[i+3]) ? b[i+3] : ' ');
|
||||
}
|
||||
}
|
||||
fprintf(fd, "----------------\t------------------\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_fprintf - print netlink message to file
|
||||
* \param fd pointer to file type
|
||||
* \param data pointer to the buffer that contains messages to be printed
|
||||
* \param datalen length of data stored in the buffer
|
||||
* \param extra_header_size size of the extra header (if any)
|
||||
*
|
||||
* This function prints the netlink header to a file handle.
|
||||
* It may be useful for debugging purposes. One example of the output
|
||||
* is the following:
|
||||
*
|
||||
*\verbatim
|
||||
---------------- ------------------
|
||||
| 0000000040 | | message length |
|
||||
| 00016 | R-A- | | type | flags |
|
||||
| 1289148991 | | sequence number|
|
||||
| 0000000000 | | port ID |
|
||||
---------------- ------------------
|
||||
| 00 00 00 00 | | extra header |
|
||||
| 00 00 00 00 | | extra header |
|
||||
| 01 00 00 00 | | extra header |
|
||||
| 01 00 00 00 | | extra header |
|
||||
|00008|--|00003| |len |flags| type|
|
||||
| 65 74 68 30 | | data | e t h 0
|
||||
---------------- ------------------
|
||||
\endverbatim
|
||||
*
|
||||
* This example above shows the netlink message that is send to kernel-space
|
||||
* to set up the link interface eth0. The netlink and attribute header data
|
||||
* are displayed in base 10 whereas the extra header and the attribute payload
|
||||
* are expressed in base 16. The possible flags in the netlink header are:
|
||||
*
|
||||
* - R, that indicates that NLM_F_REQUEST is set.
|
||||
* - M, that indicates that NLM_F_MULTI is set.
|
||||
* - A, that indicates that NLM_F_ACK is set.
|
||||
* - E, that indicates that NLM_F_ECHO is set.
|
||||
*
|
||||
* The lack of one flag is displayed with '-'. On the other hand, the possible
|
||||
* attribute flags available are:
|
||||
*
|
||||
* - N, that indicates that NLA_F_NESTED is set.
|
||||
* - B, that indicates that NLA_F_NET_BYTEORDER is set.
|
||||
*/
|
||||
void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen,
|
||||
size_t extra_header_size)
|
||||
{
|
||||
const struct nlmsghdr *nlh = data;
|
||||
int len = datalen;
|
||||
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
mnl_nlmsg_fprintf_header(fd, nlh);
|
||||
mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size);
|
||||
nlh = mnl_nlmsg_next(nlh, &len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup batch Netlink message batch helpers
|
||||
*
|
||||
* This library provides helpers to batch several messages into one single
|
||||
* datagram. These helpers do not perform strict memory boundary checkings.
|
||||
*
|
||||
* The following figure represents a Netlink message batch:
|
||||
*
|
||||
* |<-------------- MNL_SOCKET_BUFFER_SIZE ------------->|
|
||||
* |<-------------------- batch ------------------>| |
|
||||
* |-----------|-----------|-----------|-----------|-----------|
|
||||
* |<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|
|
||||
* |-----------|-----------|-----------|-----------|-----------|
|
||||
* ^ ^
|
||||
* | |
|
||||
* message N message N+1
|
||||
*
|
||||
* To start the batch, you have to call mnl_nlmsg_batch_start() and you can
|
||||
* use mnl_nlmsg_batch_stop() to release it.
|
||||
*
|
||||
* You have to invoke mnl_nlmsg_batch_next() to get room for a new message
|
||||
* in the batch. If this function returns NULL, it means that the last
|
||||
* message that was added (message N+1 in the figure above) does not fit the
|
||||
* batch. Thus, you have to send the batch (which includes until message N)
|
||||
* and, then, you have to call mnl_nlmsg_batch_reset() to re-initialize
|
||||
* the batch (this moves message N+1 to the head of the buffer). For that
|
||||
* reason, the buffer that you have to use to store the batch must be double
|
||||
* of MNL_SOCKET_BUFFER_SIZE to ensure that the last message (message N+1)
|
||||
* that did not fit into the batch is written inside valid memory boundaries.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct mnl_nlmsg_batch {
|
||||
/* the buffer that is used to store the batch. */
|
||||
void *buf;
|
||||
size_t limit;
|
||||
size_t buflen;
|
||||
/* the current netlink message in the batch. */
|
||||
void *cur;
|
||||
bool overflow;
|
||||
};
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_start - initialize a batch
|
||||
* \param buf pointer to the buffer that will store this batch
|
||||
* \param limit maximum size of the batch (should be MNL_SOCKET_BUFFER_SIZE).
|
||||
*
|
||||
* The buffer that you pass must be double of MNL_SOCKET_BUFFER_SIZE. The
|
||||
* limit must be half of the buffer size, otherwise expect funny memory
|
||||
* corruptions 8-).
|
||||
*
|
||||
* You can allocate the buffer that you use to store the batch in the stack or
|
||||
* the heap, no restrictions in this regard. This function returns NULL on
|
||||
* error.
|
||||
*/
|
||||
struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf,
|
||||
size_t limit)
|
||||
{
|
||||
struct mnl_nlmsg_batch *b;
|
||||
|
||||
b = malloc(sizeof(struct mnl_nlmsg_batch));
|
||||
if (b == NULL)
|
||||
return NULL;
|
||||
|
||||
b->buf = buf;
|
||||
b->limit = limit;
|
||||
b->buflen = 0;
|
||||
b->cur = buf;
|
||||
b->overflow = false;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_stop - release a batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function releases the batch allocated by mnl_nlmsg_batch_start().
|
||||
*/
|
||||
void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
free(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_next - get room for the next message in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns false if the last message did not fit into the
|
||||
* batch. Otherwise, it prepares the batch to provide room for the new
|
||||
* Netlink message in the batch and returns true.
|
||||
*
|
||||
* You have to put at least one message in the batch before calling this
|
||||
* function, otherwise your application is likely to crash.
|
||||
*/
|
||||
bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
struct nlmsghdr *nlh = b->cur;
|
||||
|
||||
if (b->buflen + nlh->nlmsg_len > b->limit) {
|
||||
b->overflow = true;
|
||||
return false;
|
||||
}
|
||||
b->cur = b->buf + b->buflen + nlh->nlmsg_len;
|
||||
b->buflen += nlh->nlmsg_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_reset - reset the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function allows to reset a batch, so you can reuse it to create a
|
||||
* new one. This function moves the last message which does not fit the
|
||||
* batch to the head of the buffer, if any.
|
||||
*/
|
||||
void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
if (b->overflow) {
|
||||
struct nlmsghdr *nlh = b->cur;
|
||||
memcpy(b->buf, b->cur, nlh->nlmsg_len);
|
||||
b->buflen = nlh->nlmsg_len;
|
||||
b->cur = b->buf + b->buflen;
|
||||
b->overflow = false;
|
||||
} else {
|
||||
b->buflen = 0;
|
||||
b->cur = b->buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_size - get current size of the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns the current size of the batch.
|
||||
*/
|
||||
size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buflen;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_head - get head of this batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns a pointer to the head of the batch, which is the
|
||||
* beginning of the buffer that is used.
|
||||
*/
|
||||
void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_current - returns current position in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns a pointer to the current position in the buffer
|
||||
* that is used to store the batch.
|
||||
*/
|
||||
void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_nlmsg_batch_is_empty - check if there is any message in the batch
|
||||
* \param b pointer to batch
|
||||
*
|
||||
* This function returns true if the batch is empty.
|
||||
*/
|
||||
bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
|
||||
{
|
||||
return b->buflen == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -1,351 +0,0 @@
|
||||
/*
|
||||
* (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "libmnl.h"
|
||||
|
||||
/**
|
||||
* \mainpage
|
||||
*
|
||||
* libmnl is a minimalistic user-space library oriented to Netlink developers.
|
||||
* There are a lot of common tasks in parsing, validating, constructing of
|
||||
* both the Netlink header and TLVs that are repetitive and easy to get wrong.
|
||||
* This library aims to provide simple helpers that allows you to avoid
|
||||
* re-inventing the wheel in common Netlink tasks.
|
||||
*
|
||||
* \verbatim
|
||||
"Simplify, simplify" -- Henry David Thoureau. Walden (1854)
|
||||
\endverbatim
|
||||
*
|
||||
* The acronym libmnl stands for LIBrary Minimalistic NetLink.
|
||||
*
|
||||
* libmnl homepage is:
|
||||
* http://www.netfilter.org/projects/libmnl/
|
||||
*
|
||||
* \section features Main Features
|
||||
* - Small: the shared library requires around 30KB for an x86-based computer.
|
||||
* - Simple: this library avoids complex abstractions that tend to hide Netlink
|
||||
* details. It avoids elaborated object-oriented infrastructure and complex
|
||||
* callback-based workflow.
|
||||
* - Easy to use: the library simplifies the work for Netlink-wise developers.
|
||||
* It provides functions to make socket handling, message building,
|
||||
* validating, parsing and sequence tracking, easier.
|
||||
* - Easy to re-use: you can use this library to build your own abstraction
|
||||
* layer upon this library, if you want to provide another library that
|
||||
* hides Netlink details to your users.
|
||||
* - Decoupling: the interdependency of the main bricks that compose this
|
||||
* library is reduced, i.e. the library provides many helpers, but the
|
||||
* programmer is not forced to use them.
|
||||
*
|
||||
* \section licensing Licensing terms
|
||||
* This library is released under the LGPLv2.1 or any later (at your option).
|
||||
*
|
||||
* \section Dependencies
|
||||
* You have to install the Linux kernel headers that you want to use to develop
|
||||
* your application. Moreover, this library requires that you have some basics
|
||||
* on Netlink.
|
||||
*
|
||||
* \section scm Git Tree
|
||||
* The current development version of libmnl can be accessed at:
|
||||
* http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=summary
|
||||
*
|
||||
* \section using Using libmnl
|
||||
* You can access several example files under examples/ in the libmnl source
|
||||
* code tree.
|
||||
*/
|
||||
|
||||
struct mnl_socket {
|
||||
int fd;
|
||||
struct sockaddr_nl addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \defgroup socket Netlink socket helpers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* mnl_socket_get_fd - obtain file descriptor from netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* This function returns the file descriptor of a given netlink socket.
|
||||
*/
|
||||
int mnl_socket_get_fd(const struct mnl_socket *nl)
|
||||
{
|
||||
return nl->fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_get_portid - obtain Netlink PortID from netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* This function returns the Netlink PortID of a given netlink socket.
|
||||
* It's a common mistake to assume that this PortID equals the process ID
|
||||
* which is not always true. This is the case if you open more than one
|
||||
* socket that is binded to the same Netlink subsystem from the same process.
|
||||
*/
|
||||
unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
|
||||
{
|
||||
return nl->addr.nl_pid;
|
||||
}
|
||||
|
||||
static struct mnl_socket *__mnl_socket_open(int bus, int flags)
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
|
||||
nl = calloc(1, sizeof(struct mnl_socket));
|
||||
if (nl == NULL)
|
||||
return NULL;
|
||||
|
||||
nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
|
||||
if (nl->fd == -1) {
|
||||
free(nl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_open - open a netlink socket
|
||||
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure.
|
||||
*/
|
||||
struct mnl_socket *mnl_socket_open(int bus)
|
||||
{
|
||||
return __mnl_socket_open(bus, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_open2 - open a netlink socket with appropriate flags
|
||||
* \param bus the netlink socket bus ID (see NETLINK_* constants)
|
||||
* \param flags the netlink socket flags (see SOCK_* constants in socket(2))
|
||||
*
|
||||
* This is similar to mnl_socket_open(), but allows to set flags like
|
||||
* SOCK_CLOEXEC at socket creation time (useful for multi-threaded programs
|
||||
* performing exec calls).
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure.
|
||||
*/
|
||||
struct mnl_socket *mnl_socket_open2(int bus, int flags)
|
||||
{
|
||||
return __mnl_socket_open(bus, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket.
|
||||
* \param fd pre-existing socket descriptor.
|
||||
*
|
||||
* On error, it returns NULL and errno is appropriately set. Otherwise, it
|
||||
* returns a valid pointer to the mnl_socket structure. It also sets the portID
|
||||
* if the socket fd is already bound and it is AF_NETLINK.
|
||||
*
|
||||
* Note that mnl_socket_get_portid() returns 0 if this function is used with
|
||||
* non-netlink socket.
|
||||
*/
|
||||
struct mnl_socket *mnl_socket_fdopen(int fd)
|
||||
{
|
||||
int ret;
|
||||
struct mnl_socket *nl;
|
||||
struct sockaddr_nl addr;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_nl);
|
||||
|
||||
ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len);
|
||||
if (ret == -1)
|
||||
return NULL;
|
||||
|
||||
nl = calloc(1, sizeof(struct mnl_socket));
|
||||
if (nl == NULL)
|
||||
return NULL;
|
||||
|
||||
nl->fd = fd;
|
||||
if (addr.nl_family == AF_NETLINK)
|
||||
nl->addr = addr;
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_bind - bind netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param groups the group of message you're interested in
|
||||
* \param pid the port ID you want to use (use zero for automatic selection)
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set. On
|
||||
* success, 0 is returned. You can use MNL_SOCKET_AUTOPID which is 0 for
|
||||
* automatic port ID selection.
|
||||
*/
|
||||
int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups,
|
||||
pid_t pid)
|
||||
{
|
||||
int ret;
|
||||
socklen_t addr_len;
|
||||
|
||||
nl->addr.nl_family = AF_NETLINK;
|
||||
nl->addr.nl_groups = groups;
|
||||
nl->addr.nl_pid = pid;
|
||||
|
||||
ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
addr_len = sizeof(nl->addr);
|
||||
ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (addr_len != sizeof(nl->addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (nl->addr.nl_family != AF_NETLINK) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_sendto - send a netlink message of a certain size
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param buf buffer containing the netlink message to be sent
|
||||
* \param len number of bytes in the buffer that you want to send
|
||||
*
|
||||
* On error, it returns -1 and errno is appropriately set. Otherwise, it
|
||||
* returns the number of bytes sent.
|
||||
*/
|
||||
ssize_t mnl_socket_sendto(const struct mnl_socket *nl,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
static const struct sockaddr_nl snl = {
|
||||
.nl_family = AF_NETLINK
|
||||
};
|
||||
return sendto(nl->fd, buf, len, 0,
|
||||
(struct sockaddr *) &snl, sizeof(snl));
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_recvfrom - receive a netlink message
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param buf buffer that you want to use to store the netlink message
|
||||
* \param bufsiz size of the buffer passed to store the netlink message
|
||||
*
|
||||
* On error, it returns -1 and errno is appropriately set. If errno is set
|
||||
* to ENOSPC, it means that the buffer that you have passed to store the
|
||||
* netlink message is too small, so you have received a truncated message.
|
||||
* To avoid this, you have to allocate a buffer of MNL_SOCKET_BUFFER_SIZE
|
||||
* (which is 8KB, see linux/netlink.h for more information). Using this
|
||||
* buffer size ensures that your buffer is big enough to store the netlink
|
||||
* message without truncating it.
|
||||
*/
|
||||
ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl,
|
||||
void *buf, size_t bufsiz)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct sockaddr_nl addr;
|
||||
struct iovec iov = {
|
||||
.iov_base = buf,
|
||||
.iov_len = bufsiz,
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &addr,
|
||||
.msg_namelen = sizeof(struct sockaddr_nl),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = NULL,
|
||||
.msg_controllen = 0,
|
||||
.msg_flags = 0,
|
||||
};
|
||||
ret = recvmsg(nl->fd, &msg, 0);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_close - close a given netlink socket
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
* On success, it returns 0.
|
||||
*/
|
||||
int mnl_socket_close(struct mnl_socket *nl)
|
||||
{
|
||||
int ret = close(nl->fd);
|
||||
free(nl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_setsockopt - set Netlink socket option
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param type type of Netlink socket options
|
||||
* \param buf the buffer that contains the data about this option
|
||||
* \param len the size of the buffer passed
|
||||
*
|
||||
* This function allows you to set some Netlink socket option. As of writing
|
||||
* this (see linux/netlink.h), the existing options are:
|
||||
*
|
||||
* - \#define NETLINK_ADD_MEMBERSHIP 1
|
||||
* - \#define NETLINK_DROP_MEMBERSHIP 2
|
||||
* - \#define NETLINK_PKTINFO 3
|
||||
* - \#define NETLINK_BROADCAST_ERROR 4
|
||||
* - \#define NETLINK_NO_ENOBUFS 5
|
||||
*
|
||||
* In the early days, Netlink only supported 32 groups expressed in a
|
||||
* 32-bits mask. However, since 2.6.14, Netlink may have up to 2^32 multicast
|
||||
* groups but you have to use setsockopt() with NETLINK_ADD_MEMBERSHIP to
|
||||
* join a given multicast group. This function internally calls setsockopt()
|
||||
* to join a given netlink multicast group. You can still use mnl_bind()
|
||||
* and the 32-bit mask to join a set of Netlink multicast groups.
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
*/
|
||||
int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
|
||||
void *buf, socklen_t len)
|
||||
{
|
||||
return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* mnl_socket_getsockopt - get a Netlink socket option
|
||||
* \param nl netlink socket obtained via mnl_socket_open()
|
||||
* \param type type of Netlink socket options
|
||||
* \param buf pointer to the buffer to store the value of this option
|
||||
* \param len size of the information written in the buffer
|
||||
*
|
||||
* On error, this function returns -1 and errno is appropriately set.
|
||||
*/
|
||||
int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
|
||||
void *buf, socklen_t *len)
|
||||
{
|
||||
return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,67 +0,0 @@
|
||||
[Setting]
|
||||
qmap_num=4
|
||||
|
||||
[profile1]
|
||||
apn=1234567890
|
||||
user=qwertyuio
|
||||
password=asdfghjkl
|
||||
auth=2
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile2]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=0
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile3]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=0
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile4]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=0
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile5]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile6]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile7]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
[profile8]
|
||||
apn=ctnet
|
||||
user=
|
||||
password=
|
||||
auth=
|
||||
ipfamily=1
|
||||
pin=
|
||||
|
||||
@@ -1,438 +0,0 @@
|
||||
#include "QMIThread.h"
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
#include <net/if.h>
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
|
||||
static size_t fibo_fread(const char *filename, void *buf, size_t size)
|
||||
{
|
||||
FILE *fp = fopen(filename, "r");
|
||||
size_t n = 0;
|
||||
|
||||
memset(buf, 0x00, size);
|
||||
|
||||
if (fp) {
|
||||
n = fread(buf, 1, size, fp);
|
||||
if (n <= 0 || n == size) {
|
||||
dbg_time(
|
||||
"warnning: fail to fread(%s), fread=%zd, buf_size=%zd, "
|
||||
"errno: %d (%s)",
|
||||
__func__, filename, n, size, errno, strerror(errno));
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return n > 0 ? n : 0;
|
||||
}
|
||||
|
||||
static size_t fibo_fwrite(const char *filename, const void *buf, size_t size)
|
||||
{
|
||||
FILE *fp = fopen(filename, "w");
|
||||
size_t n = 0;
|
||||
|
||||
if (fp) {
|
||||
n = fwrite(buf, 1, size, fp);
|
||||
if (n != size) {
|
||||
dbg_time(
|
||||
"warnning: fail to fwrite(%s), fwrite=%zd, buf_size=%zd, "
|
||||
"errno: %d (%s)",
|
||||
__func__, filename, n, size, errno, strerror(errno));
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return n > 0 ? n : 0;
|
||||
}
|
||||
|
||||
static int fibo_iface_is_in_bridge(const char *iface)
|
||||
{
|
||||
char filename[256];
|
||||
|
||||
snprintf(filename, sizeof(filename), "/sys/class/net/%s/brport", iface);
|
||||
return (access(filename, F_OK) == 0 || errno != ENOENT);
|
||||
}
|
||||
|
||||
int fibo_bridge_mode_detect(PROFILE_T *profile)
|
||||
{
|
||||
const char *ifname = profile->qmapnet_adapter ? profile->qmapnet_adapter
|
||||
: profile->usbnet_adapter;
|
||||
const char *driver;
|
||||
char bridge_mode[128];
|
||||
char bridge_ipv4[128];
|
||||
char ipv4[128];
|
||||
char buf[64];
|
||||
size_t n;
|
||||
int in_bridge;
|
||||
|
||||
driver = profile->driver_name;
|
||||
snprintf(bridge_mode, sizeof(bridge_mode), "/sys/class/net/%s/bridge_mode",
|
||||
ifname);
|
||||
snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/class/net/%s/bridge_ipv4",
|
||||
ifname);
|
||||
|
||||
if (access(bridge_mode, F_OK) && errno == ENOENT) {
|
||||
snprintf(bridge_mode, sizeof(bridge_mode),
|
||||
"/sys/module/%s/parameters/bridge_mode", driver);
|
||||
snprintf(bridge_ipv4, sizeof(bridge_ipv4),
|
||||
"/sys/module/%s/parameters/bridge_ipv4", driver);
|
||||
|
||||
if (access(bridge_mode, F_OK) && errno == ENOENT) {
|
||||
bridge_mode[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
in_bridge = fibo_iface_is_in_bridge(ifname);
|
||||
if (in_bridge) {
|
||||
dbg_time("notice: iface %s had add to bridge\n", ifname);
|
||||
}
|
||||
|
||||
if (in_bridge && bridge_mode[0] == '\0') {
|
||||
dbg_time("warnning: can not find bride_mode file for %s\n", ifname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = fibo_fread(bridge_mode, buf, sizeof(buf));
|
||||
|
||||
if (in_bridge) {
|
||||
if (n <= 0 || buf[0] == '0') {
|
||||
dbg_time("warnning: should set 1 to bride_mode file for %s\n",
|
||||
ifname);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (n <= 0 || buf[0] == '0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memset(ipv4, 0, sizeof(ipv4));
|
||||
|
||||
if (strstr(bridge_ipv4, "/sys/class/net/") || profile->qmap_mode == 0 ||
|
||||
profile->qmap_mode == 1) {
|
||||
snprintf(ipv4, sizeof(ipv4), "0x%x", profile->ipv4.Address);
|
||||
dbg_time("echo '%s' > %s", ipv4, bridge_ipv4);
|
||||
fibo_fwrite(bridge_ipv4, ipv4, strlen(ipv4));
|
||||
} else {
|
||||
snprintf(ipv4, sizeof(ipv4), "0x%x:%d", profile->ipv4.Address,
|
||||
profile->muxid);
|
||||
dbg_time("echo '%s' > %s", ipv4, bridge_ipv4);
|
||||
fibo_fwrite(bridge_ipv4, ipv4, strlen(ipv4));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
void fibo_get_driver_info(PROFILE_T *profile, RMNET_INFO *rmnet_info) {
|
||||
int ifc_ctl_sock;
|
||||
struct ifreq ifr;
|
||||
int rc;
|
||||
int request = 0x89F3;
|
||||
unsigned char data[512];
|
||||
|
||||
memset(rmnet_info, 0x00, sizeof(*rmnet_info));
|
||||
|
||||
ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ifc_ctl_sock <= 0) {
|
||||
dbg_time("socket() failed: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ);
|
||||
ifr.ifr_name[IFNAMSIZ - 1] = 0;
|
||||
ifr.ifr_ifru.ifru_data = (void *)data;
|
||||
rc = ioctl(ifc_ctl_sock, request, &ifr);
|
||||
if (rc < 0) {
|
||||
dbg_time("ioctl(0x%x, qmap_settings) failed: %s, rc=%d", request, strerror(errno), rc);
|
||||
}
|
||||
else {
|
||||
memcpy(rmnet_info, data, sizeof(*rmnet_info));
|
||||
}
|
||||
|
||||
close(ifc_ctl_sock);
|
||||
}
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
int fibo_qmap_mode_detect(PROFILE_T *profile)
|
||||
{
|
||||
int n;
|
||||
char buf[128];
|
||||
char qmap_netcard[128];
|
||||
struct {
|
||||
char filename[255 * 2];
|
||||
char linkname[255 * 2];
|
||||
} * pl;
|
||||
|
||||
pl = (typeof(pl))malloc(sizeof(*pl));
|
||||
|
||||
snprintf(pl->linkname, sizeof(pl->linkname),
|
||||
"/sys/class/net/%s/device/driver", profile->usbnet_adapter);
|
||||
n = readlink(pl->linkname, pl->filename, sizeof(pl->filename));
|
||||
pl->filename[n] = '\0';
|
||||
while (pl->filename[n] != '/') n--;
|
||||
profile->driver_name = strdup(&pl->filename[n + 1]);
|
||||
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037
|
||||
fibo_get_driver_info(profile, &profile->rmnet_info);
|
||||
if (profile->rmnet_info.size) {
|
||||
profile->qmap_mode = profile->rmnet_info.qmap_mode;
|
||||
if (profile->qmap_mode) {
|
||||
int offset_id = profile->pdp - 1;
|
||||
|
||||
if (profile->qmap_mode == 1)
|
||||
offset_id = 0;
|
||||
profile->muxid = profile->rmnet_info.mux_id[offset_id];
|
||||
profile->qmapnet_adapter = strdup( profile->rmnet_info.ifname[offset_id]);
|
||||
profile->qmap_size = profile->rmnet_info.rx_urb_size;
|
||||
profile->qmap_version = profile->rmnet_info.qmap_version;
|
||||
}
|
||||
|
||||
goto _out;
|
||||
}
|
||||
//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037
|
||||
|
||||
if (qmidev_is_pciemhi(profile->qmichannel)) {
|
||||
profile->qmap_mode = 1;
|
||||
|
||||
if (profile->muxid == 0 || profile->muxid == 0x81)
|
||||
{
|
||||
profile->muxid = 0x81;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (profile->muxid < 0x80)
|
||||
profile->muxid += 0x81;
|
||||
profile->qmap_mode = 2;
|
||||
}
|
||||
|
||||
profile->qmapnet_adapter = strdup(profile->usbnet_adapter);
|
||||
goto _final_process;
|
||||
}
|
||||
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
|
||||
//2021-01-27 willa.liu@fibocom.com changed begin for support mantis 0068849
|
||||
if (access(pl->filename, F_OK) == 0) {
|
||||
dbg_time("access %s", pl->filename);
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno,
|
||||
strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837
|
||||
/*
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/module/%s/parameters/qmap_num", profile->driver_name);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
|
||||
snprintf(
|
||||
pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/device/driver/module/parameters/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
//2021-02-01 willa.liu@fibocom.com changed end for support mantis 0069837
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_mode",
|
||||
profile->usbnet_adapter);
|
||||
|
||||
if (access(pl->filename, F_OK) == 0) {
|
||||
dbg_time("access %s", pl->filename);
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno,
|
||||
strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!access(pl->filename, R_OK))
|
||||
{
|
||||
n = fibo_fread(pl->filename, buf, sizeof(buf));
|
||||
if(n > 0)
|
||||
{
|
||||
profile->qmap_mode = atoi(buf);
|
||||
if(profile->qmap_mode >= 1 && qmidev_is_pciemhi(profile->qmichannel))
|
||||
{
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80;
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if(qmidev_is_gobinet(profile->qmichannel) || qmidev_is_qmiwwan(profile->qmichannel))
|
||||
{
|
||||
if(profile->qmap_mode > 1)
|
||||
{
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80;
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if(profile->qmap_mode == 1)
|
||||
{
|
||||
profile->muxid = 0x81;
|
||||
profile->qmapnet_adapter = strdup(profile->usbnet_adapter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (0) {
|
||||
profile->qmap_mode = atoi(buf);
|
||||
|
||||
if (profile->qmap_mode > 1 && qmidev_is_gobinet(profile->qmichannel)) {
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80; // muxis is 0x8X for PDN-X
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if (profile->qmap_mode >= 1 && !qmidev_is_gobinet(profile->qmichannel)) {
|
||||
profile->muxid =
|
||||
profile->pdp + 0x80; // muxis is 0x8X for PDN-X
|
||||
sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
if (profile->qmap_mode == 1 && qmidev_is_gobinet(profile->qmichannel)) {
|
||||
profile->muxid = 0x81;
|
||||
profile->qmapnet_adapter = strdup(profile->usbnet_adapter);
|
||||
//2021-01-27 willa.liu@fibocom.com changed end for support mantis 0068849
|
||||
|
||||
}
|
||||
}
|
||||
} else if (qmidev_is_qmiwwan(profile->qmichannel)) {
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/qmimux%d",
|
||||
profile->pdp - 1);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
}
|
||||
goto _out;
|
||||
}
|
||||
|
||||
// upstream Kernel Style QMAP qmi_wwan.c
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter);
|
||||
n = fibo_fread(pl->filename, buf, sizeof(buf));
|
||||
if (n >= 5) {
|
||||
profile->qmap_mode = n / 5; // 0x81\n0x82\n0x83\n
|
||||
if (profile->qmap_mode > 1) {
|
||||
// PDN-X map to qmimux-X
|
||||
profile->muxid = (buf[5 * (profile->pdp - 1) + 2] - '0') * 16 +
|
||||
(buf[5 * (profile->pdp - 1) + 3] - '0');
|
||||
sprintf(qmap_netcard, "qmimux%d", profile->pdp - 1);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
} else if (profile->qmap_mode == 1) {
|
||||
profile->muxid =
|
||||
(buf[5 * 0 + 2] - '0') * 16 + (buf[5 * 0 + 3] - '0');
|
||||
sprintf(qmap_netcard, "qmimux%d", 0);
|
||||
profile->qmapnet_adapter = strdup(qmap_netcard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_out:
|
||||
if (profile->qmap_mode) {
|
||||
profile->qmap_size = 16 * 1024;
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/qmap_size", profile->usbnet_adapter);
|
||||
if (!access(pl->filename, R_OK)) {
|
||||
size_t n;
|
||||
char buf[32];
|
||||
n = fibo_fread(pl->filename, buf, sizeof(buf));
|
||||
if (n > 0) {
|
||||
profile->qmap_size = atoi(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_final_process:
|
||||
if (profile->qmap_mode)
|
||||
dbg_time("qmap_mode = %d, muxid = 0x%02x, qmap_netcard = %s",
|
||||
profile->qmap_mode, profile->muxid, profile->qmapnet_adapter);
|
||||
|
||||
free(pl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fibo_qmap_mode_set(PROFILE_T *profile)
|
||||
{
|
||||
int n;
|
||||
char buf[128];
|
||||
struct {
|
||||
char filename[255 * 2];
|
||||
char linkname[255 * 2];
|
||||
} * pl;
|
||||
|
||||
if (qmidev_is_pciemhi(profile->qmichannel))
|
||||
{
|
||||
dbg_time("pcie mode exit fibo_qmap_mode_set ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pl = (typeof(pl))malloc(sizeof(*pl));
|
||||
|
||||
snprintf(pl->linkname, sizeof(pl->linkname),
|
||||
"/sys/class/net/%s/device/driver", profile->usbnet_adapter);
|
||||
n = readlink(pl->linkname, pl->filename, sizeof(pl->filename));
|
||||
pl->filename[n] = '\0';
|
||||
while (pl->filename[n] != '/') n--;
|
||||
profile->driver_name = strdup(&pl->filename[n + 1]);
|
||||
|
||||
snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno,
|
||||
strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
|
||||
snprintf(pl->filename, sizeof(pl->filename),
|
||||
"/sys/module/%s/parameters/qmap_mnum", profile->driver_name);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
|
||||
snprintf(
|
||||
pl->filename, sizeof(pl->filename),
|
||||
"/sys/class/net/%s/device/driver/module/parameters/qmap_num",
|
||||
profile->usbnet_adapter);
|
||||
if (access(pl->filename, R_OK)) {
|
||||
if (errno != ENOENT) {
|
||||
dbg_time("fail to access %s, errno: %d (%s)", pl->filename,
|
||||
errno, strerror(errno));
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!access(pl->filename, R_OK)) {
|
||||
snprintf(buf, sizeof(buf), "%d", profile->pdpnum);
|
||||
n = fibo_fwrite(pl->filename, buf, strlen(buf));
|
||||
}
|
||||
|
||||
_out:
|
||||
|
||||
free(pl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817
|
||||
#include "QMIThread.h"
|
||||
#include "query_pcie_mode.h"
|
||||
int speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300,//
|
||||
B38400, B19200, B9600, B4800, B2400, B1200, B300,
|
||||
};
|
||||
int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300,
|
||||
38400, 19200, 9600, 4800, 2400, 1200, 300,
|
||||
};
|
||||
|
||||
int get_pcie_mode_debug = 0;
|
||||
|
||||
//2021-02-24 willa.liu@fibocom.com changed begin for support eipd SN-20210129001
|
||||
int get_private_gateway_debug = 1;
|
||||
//2021-02-24 willa.liu@fibocom.com changed end for support eipd SN-20210129001
|
||||
|
||||
//static int xset1(int fd, struct termios *tio, const char *device)
|
||||
int xset1(int fd, struct termios *tio, const char *device)
|
||||
{
|
||||
int ret = tcsetattr(fd, TCSAFLUSH, tio);
|
||||
|
||||
if (ret) {
|
||||
printf("can't tcsetattr for %s", device);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// set raw tty mode
|
||||
//static void xget1(int fd, struct termios *t, struct termios *oldt)
|
||||
void xget1(int fd, struct termios *t, struct termios *oldt)
|
||||
{
|
||||
tcgetattr(fd, oldt);
|
||||
*t = *oldt;
|
||||
cfmakeraw(t);
|
||||
// t->c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
|
||||
// t->c_iflag &= ~(BRKINT|IXON|ICRNL);
|
||||
// t->c_oflag &= ~(ONLCR);
|
||||
// t->c_cc[VMIN] = 1;
|
||||
// t->c_cc[VTIME] = 0;
|
||||
}
|
||||
|
||||
//static int get_pcie_mode()
|
||||
int get_pcie_mode()
|
||||
//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817
|
||||
{
|
||||
int i;
|
||||
int fd;
|
||||
int ret;
|
||||
char buffer[409600] = {0};
|
||||
int rate;
|
||||
char* sendbuffer;
|
||||
int totallen = 0;
|
||||
fd_set readfds;
|
||||
struct timeval timeout;
|
||||
struct termios tio0, tiosfd, tio;
|
||||
|
||||
int timeoutVal = 5;
|
||||
|
||||
char *dev = "/dev/ttyUSB1"; //The port under Linux is operated by opening the device file
|
||||
rate = 115200;
|
||||
sendbuffer = "at+gtpcie=3";
|
||||
printf ( "dev: %s\nrate:%d\nsendbuffer:%s\n", dev,rate,sendbuffer);
|
||||
|
||||
fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
goto ERR;
|
||||
fcntl(fd, F_SETFL, O_RDWR);
|
||||
|
||||
// put device to "raw mode"
|
||||
xget1(fd, &tio, &tiosfd);
|
||||
// set device speed
|
||||
for ( i = 0;i < sizeof ( speed_arr ) / sizeof ( int );i++ )
|
||||
{
|
||||
if ( rate == name_arr[i] ) //Judge if the pass is equal to the pass
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i >= sizeof ( speed_arr ) / sizeof ( int ))
|
||||
{
|
||||
printf("bound rate set failed\n");
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
cfsetspeed(&tio, speed_arr[i]);
|
||||
if (xset1(fd, &tio, dev))
|
||||
goto ERR;
|
||||
|
||||
tcflush ( fd, TCIOFLUSH );
|
||||
|
||||
sprintf(buffer, "%s\r", sendbuffer);
|
||||
ret = write ( fd, buffer, strlen(buffer) );
|
||||
if(ret < 0)
|
||||
{
|
||||
printf ( "write failed\n" );
|
||||
goto ERR;
|
||||
}
|
||||
if(get_pcie_mode_debug)printf("write %d\n", ret);
|
||||
|
||||
FD_ZERO ( &readfds );
|
||||
FD_SET ( fd, &readfds );
|
||||
|
||||
while(1)
|
||||
{
|
||||
timeout.tv_sec = timeoutVal;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
ret = select ( fd+1, &readfds, ( fd_set * ) 0, ( fd_set * ) 0, &timeout );
|
||||
if(ret > 0)
|
||||
{
|
||||
ret = read ( fd, buffer+totallen, sizeof(buffer)-totallen-1 );
|
||||
if(ret < 0)
|
||||
{
|
||||
printf ( "read failed\n" );
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
totallen += ret;
|
||||
buffer[totallen] = '\0';
|
||||
if(get_pcie_mode_debug)printf("read %d(%s)\n", ret, &buffer[totallen-ret]);
|
||||
if(totallen == sizeof(buffer)-1)
|
||||
break;
|
||||
|
||||
if(strstr(buffer,"\nOK") || strstr(buffer,"\nERROR")
|
||||
|| strstr(buffer,"\n+CME ERROR:") || strstr(buffer,"\n+CMS ERROR:"))
|
||||
{
|
||||
if(get_pcie_mode_debug)printf("match OK/ERROR");
|
||||
if(get_pcie_mode_debug)printf("%s", buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ( "select timeout\n" );
|
||||
goto ERR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tcsetattr(fd, TCSAFLUSH, &tiosfd);
|
||||
//printf("buffer:\n %s\n", buffer);
|
||||
printf("%s\n", buffer);
|
||||
if(strstr(buffer,"\nERROR") || strstr(buffer,"\n+CME ERROR:") || strstr(buffer,"\n+CMS ERROR:"))
|
||||
goto ERR;
|
||||
|
||||
close ( fd );
|
||||
return 0;
|
||||
ERR:
|
||||
if(fd > 0)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifndef __QUERY_PCIE_MODE__
|
||||
#define __QUERY_PCIE_MODE__
|
||||
|
||||
extern int speed_arr[14];
|
||||
extern int name_arr[14];
|
||||
|
||||
extern int get_pcie_mode_debug;
|
||||
|
||||
extern int get_private_gateway_debug;
|
||||
|
||||
extern int xset1(int fd, struct termios *tio, const char *device);
|
||||
|
||||
// set raw tty mode
|
||||
extern void xget1(int fd, struct termios *t, struct termios *oldt);
|
||||
extern int get_pcie_mode();
|
||||
|
||||
#endif
|
||||
@@ -1,289 +0,0 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <endian.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
#include "util.h"
|
||||
|
||||
static int dibbler_client_alive = 0;
|
||||
|
||||
static int fibo_system(const char *shell_cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
dbg_time("%s", shell_cmd);
|
||||
ret = system(shell_cmd);
|
||||
if (ret) {
|
||||
// dbg_time("Fail to system(\"%s\") = %d, errno: %d (%s)", shell_cmd,
|
||||
// ret, errno, strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fibo_set_mtu(const char *ifname, int ifru_mtu)
|
||||
{
|
||||
int inet_sock;
|
||||
struct ifreq ifr;
|
||||
|
||||
inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (inet_sock > 0) {
|
||||
strcpy(ifr.ifr_name, ifname);
|
||||
|
||||
if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) {
|
||||
if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) {
|
||||
dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu,
|
||||
ifru_mtu);
|
||||
ifr.ifr_ifru.ifru_mtu = ifru_mtu;
|
||||
ioctl(inet_sock, SIOCSIFMTU, &ifr);
|
||||
}
|
||||
}
|
||||
|
||||
close(inet_sock);
|
||||
}
|
||||
}
|
||||
|
||||
static void *udhcpc_thread_function(void *arg)
|
||||
{
|
||||
FILE *udhcpc_fp;
|
||||
char *udhcpc_cmd = (char *)arg;
|
||||
|
||||
if (udhcpc_cmd == NULL)
|
||||
return NULL;
|
||||
|
||||
dbg_time("%s", udhcpc_cmd);
|
||||
udhcpc_fp = popen(udhcpc_cmd, "r");
|
||||
free(udhcpc_cmd);
|
||||
if (udhcpc_fp) {
|
||||
char buf[0xff];
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
while ((fgets(buf, sizeof(buf) - 1, udhcpc_fp)) != NULL) {
|
||||
if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n'))
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
dbg_time("%s", buf);
|
||||
}
|
||||
|
||||
pclose(udhcpc_fp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fibo_set_driver_link_state(PROFILE_T *profile, int link_state)
|
||||
{
|
||||
char link_file[128];
|
||||
int fd;
|
||||
int new_state = 0;
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state",
|
||||
profile->usbnet_adapter);
|
||||
fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd == -1) {
|
||||
if (errno != ENOENT)
|
||||
dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile->qmap_mode <= 1)
|
||||
new_state = !!link_state;
|
||||
else {
|
||||
// 0x80 means link off this pdp
|
||||
new_state = (link_state ? 0x00 : 0x80) + profile->pdp;
|
||||
}
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "%d\n", new_state);
|
||||
write(fd, link_file, sizeof(link_file));
|
||||
|
||||
if (link_state == 0 && profile->qmap_mode > 1) {
|
||||
size_t rc;
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
rc = read(fd, link_file, sizeof(link_file));
|
||||
if (rc > 1 && (!strcasecmp(link_file, "0\n") ||
|
||||
!strcasecmp(link_file, "0x0\n"))) {
|
||||
// snprintf(link_file, sizeof(link_file), "busybox ifconfig %s down",
|
||||
// profile->usbnet_adapter);
|
||||
// fibo_system(link_file);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int fibo_raw_ip_mode_check(const char *ifname)
|
||||
{
|
||||
int fd;
|
||||
char raw_ip[128];
|
||||
char shell_cmd[128];
|
||||
char mode[2] = "X";
|
||||
int mode_change = 0;
|
||||
|
||||
snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
if (access(raw_ip, F_OK))
|
||||
return 0;
|
||||
|
||||
fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd < 0) {
|
||||
dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__,
|
||||
raw_ip, errno, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
read(fd, mode, 2);
|
||||
if (mode[0] == '0' || mode[0] == 'N') {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd), "busybox ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
mode[0] = 'Y';
|
||||
write(fd, mode, 2);
|
||||
mode_change = 1;
|
||||
snprintf(shell_cmd, sizeof(shell_cmd), "busybox ifconfig %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return mode_change;
|
||||
}
|
||||
|
||||
void udhcpc_start(PROFILE_T *profile)
|
||||
{
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[128];
|
||||
|
||||
fibo_set_driver_link_state(profile, 1);
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
dbg_time("1 %s", profile->qmichannel);
|
||||
if (qmidev_is_qmiwwan(profile->qmichannel)) {
|
||||
dbg_time("2 %s", ifname);
|
||||
fibo_raw_ip_mode_check(ifname);
|
||||
}
|
||||
|
||||
if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) {
|
||||
fibo_set_mtu(ifname, (profile->ipv4.Mtu));
|
||||
}
|
||||
|
||||
fibo_system("echo 1 > /sys/module/fibo_mhi/parameters/macaddr_check");
|
||||
|
||||
//begin modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605
|
||||
// if (strcmp(ifname, profile->usbnet_adapter)) {
|
||||
// snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s up",
|
||||
// profile->usbnet_adapter);
|
||||
// fibo_system(shell_cmd);
|
||||
// }
|
||||
//begin modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605
|
||||
// For IPv6, down & up will send protocol packets, and that's needed.
|
||||
if (profile->ipv6_flag) {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
//begin modified by zhangming Added NOARP and Multilcast on flag bit commands. mantis 0050106 20200713
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s arp off multicast on", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
//begin modified by zhangming Added NOARP and Multilcast on flag bit commands. mantis 0050106 20200713
|
||||
//Modified unicom dual stack dialing unsuccessful problem
|
||||
|
||||
// for bridge mode, only one public IP, so do udhcpc manually
|
||||
if (fibo_bridge_mode_detect(profile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do DHCP using busybox tools */
|
||||
{
|
||||
char udhcpc_cmd[128];
|
||||
pthread_attr_t udhcpc_thread_attr;
|
||||
pthread_t udhcpc_thread_id;
|
||||
|
||||
pthread_attr_init(&udhcpc_thread_attr);
|
||||
pthread_attr_setdetachstate(&udhcpc_thread_attr,
|
||||
PTHREAD_CREATE_DETACHED);
|
||||
|
||||
if (profile->ipv4.Address) {
|
||||
if (access("/usr/share/udhcpc/default.script", X_OK)) {
|
||||
dbg_time(
|
||||
"Fail to access /usr/share/udhcpc/default.script, "
|
||||
"errno: %d (%s)",
|
||||
errno, strerror(errno));
|
||||
}
|
||||
|
||||
//-f,--foreground Run in foreground
|
||||
//-b,--background Background if lease is not obtained
|
||||
//-n,--now Exit if lease is not obtained
|
||||
//-q,--quit Exit after obtaining lease
|
||||
//-t,--retries N Send up to N discover packets (default 3)
|
||||
snprintf(udhcpc_cmd, sizeof(udhcpc_cmd),
|
||||
"busybox udhcpc -f -n -q -t 5 -i %s", ifname);
|
||||
|
||||
if (!access("/lib/netifd/dhcp.script", X_OK) &&
|
||||
!access("/sbin/ifup", X_OK) &&
|
||||
!access("/sbin/ifstatus", X_OK)) {
|
||||
dbg_time("you are use OpenWrt?");
|
||||
dbg_time("should not calling udhcpc manually?");
|
||||
dbg_time("should modify /etc/config/network as below?");
|
||||
dbg_time("config interface wan");
|
||||
dbg_time("\toption ifname %s", ifname);
|
||||
dbg_time("\toption proto dhcp");
|
||||
dbg_time(
|
||||
"should use \"/sbin/ifstaus wan\" to check %s 's status?",
|
||||
ifname);
|
||||
}
|
||||
|
||||
pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function,
|
||||
(void *)strdup(udhcpc_cmd));
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) {
|
||||
// module do not support DHCPv6, only support 'Router Solicit'
|
||||
// and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding,
|
||||
// Kernel do not send RS
|
||||
const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
|
||||
int forward_fd = open(forward_file, O_RDONLY);
|
||||
if (forward_fd > 0) {
|
||||
char forward_state[2];
|
||||
read(forward_fd, forward_state, 2);
|
||||
if (forward_state[0] == '1') {
|
||||
dbg_time(
|
||||
"%s enabled, kernel maybe donot send 'Router Solicit'",
|
||||
forward_file);
|
||||
}
|
||||
close(forward_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udhcpc_stop(PROFILE_T *profile)
|
||||
{
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[128];
|
||||
char reset_ip[128];
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if (dibbler_client_alive) {
|
||||
system("killall dibbler-client");
|
||||
dibbler_client_alive = 0;
|
||||
}
|
||||
//snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down",
|
||||
// profile->usbnet_adapter);
|
||||
//fibo_system(shell_cmd);
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
snprintf(reset_ip, sizeof(reset_ip) - 1, "busybox ifconfig %s 0.0.0.0", ifname);
|
||||
fibo_system(reset_ip);
|
||||
}
|
||||
@@ -1,421 +0,0 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <endian.h>
|
||||
|
||||
#include "libmnl/ifutils.h"
|
||||
#include "libmnl/dhcp/dhcp.h"
|
||||
#include "util.h"
|
||||
#include "QMIThread.h"
|
||||
|
||||
static int fibo_system(const char *shell_cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
dbg_time("%s", shell_cmd);
|
||||
ret = system(shell_cmd);
|
||||
if (ret) {
|
||||
// dbg_time("Fail to system(\"%s\") = %d, errno: %d (%s)", shell_cmd,
|
||||
// ret, errno, strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fibo_raw_ip_mode_check(const char *ifname)
|
||||
{
|
||||
int fd;
|
||||
char raw_ip[128];
|
||||
char mode[2] = "X";
|
||||
int mode_change = 0;
|
||||
|
||||
snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
if (access(raw_ip, F_OK))
|
||||
return 0;
|
||||
|
||||
fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd < 0)
|
||||
{
|
||||
dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
read(fd, mode, 2);
|
||||
if (mode[0] == '0' || mode[0] == 'N')
|
||||
{
|
||||
if_link_down(ifname);
|
||||
dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
|
||||
mode[0] = 'Y';
|
||||
write(fd, mode, 2);
|
||||
mode_change = 1;
|
||||
if_link_up(ifname);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return mode_change;
|
||||
}
|
||||
|
||||
static void fibo_set_driver_link_state(PROFILE_T *profile, int link_state)
|
||||
{
|
||||
char link_file[128];
|
||||
int fd;
|
||||
int new_state = 0;
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter);
|
||||
fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd == -1)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (profile->qmap_mode <= 1)
|
||||
new_state = !!link_state;
|
||||
else
|
||||
{
|
||||
//0x80 means link off this pdp
|
||||
new_state = (link_state ? 0x00 : 0x80) + profile->pdp;
|
||||
}
|
||||
|
||||
snprintf(link_file, sizeof(link_file), "%d\n", new_state);
|
||||
write(fd, link_file, sizeof(link_file));
|
||||
|
||||
if (link_state == 0 && profile->qmap_mode > 1)
|
||||
{
|
||||
size_t rc;
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
rc = read(fd, link_file, sizeof(link_file));
|
||||
if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n")))
|
||||
{
|
||||
// if_link_down(profile->usbnet_adapter);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void udhcpc_start(PROFILE_T *profile)
|
||||
{
|
||||
//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[512];
|
||||
|
||||
fibo_set_driver_link_state(profile, 1);
|
||||
fibo_raw_ip_mode_check(ifname);
|
||||
|
||||
if (profile->qmapnet_adapter)
|
||||
{
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu)
|
||||
{
|
||||
if_set_mtu(ifname, (profile->ipv4.Mtu));
|
||||
}
|
||||
|
||||
if (strcmp(ifname, profile->usbnet_adapter))
|
||||
{
|
||||
//if_link_up(profile->usbnet_adapter);
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", profile->usbnet_adapter);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837
|
||||
if_link_up(ifname);
|
||||
|
||||
#if 1 //for bridge mode, only one public IP, so do udhcpc manually
|
||||
if (fibo_bridge_mode_detect(profile))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// if use DHCP(should make with ${DHCP} src files)
|
||||
// do_dhcp(ifname);
|
||||
// return 0;
|
||||
/* IPv4 Addr Info */
|
||||
if (profile->ipv4.Address)
|
||||
{
|
||||
dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu);
|
||||
dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address)));
|
||||
dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask)));
|
||||
dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway)));
|
||||
dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary)));
|
||||
dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary)));
|
||||
if_set_network_v4(ifname, ntohl(profile->ipv4.Address),
|
||||
mask_to_prefix_v4(profile->ipv4.SubnetMask),
|
||||
ntohl(profile->ipv4.Gateway),
|
||||
ntohl(profile->ipv4.DnsPrimary),
|
||||
ntohl(profile->ipv4.DnsSecondary));
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_time("The IPv4 Address in profile is NULL");
|
||||
}
|
||||
|
||||
if (profile->ipv6.Address && (profile->ipv6.PrefixLengthIPAddr != 0))
|
||||
{
|
||||
//module do not support DHCPv6, only support 'Router Solicit'
|
||||
//and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS
|
||||
const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
|
||||
int forward_fd = open(forward_file, O_RDONLY);
|
||||
if (forward_fd > 0)
|
||||
{
|
||||
char forward_state[2];
|
||||
read(forward_fd, forward_state, 2);
|
||||
if (forward_state[0] == '1')
|
||||
{
|
||||
dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file);
|
||||
}
|
||||
close(forward_fd);
|
||||
}
|
||||
|
||||
dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu);
|
||||
dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address));
|
||||
dbg_time("IPv6 PrefixLengthIPAddr: %d", profile->ipv6.PrefixLengthIPAddr);
|
||||
dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway));
|
||||
dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary));
|
||||
dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary));
|
||||
if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr,
|
||||
profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_time("The IPv6 Address in profile is NULL");
|
||||
}
|
||||
}
|
||||
|
||||
void udhcpc_stop(PROFILE_T *profile)
|
||||
{
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
fibo_set_driver_link_state(profile, 0);
|
||||
|
||||
if (profile->qmapnet_adapter)
|
||||
{
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if_flush_v4_addr(ifname);
|
||||
if_flush_v6_addr(ifname);
|
||||
if_link_down(ifname);
|
||||
}
|
||||
|
||||
static void fibo_set_mtu(const char *ifname, int ifru_mtu) {
|
||||
int inet_sock;
|
||||
struct ifreq ifr;
|
||||
|
||||
inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (inet_sock > 0) {
|
||||
strcpy(ifr.ifr_name, ifname);
|
||||
|
||||
if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) {
|
||||
if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) {
|
||||
dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu , ifru_mtu);
|
||||
ifr.ifr_ifru.ifru_mtu = ifru_mtu;
|
||||
ioctl(inet_sock, SIOCSIFMTU, &ifr);
|
||||
}
|
||||
}
|
||||
|
||||
close(inet_sock);
|
||||
}
|
||||
}
|
||||
|
||||
static void* udhcpc_thread_function(void* arg) {
|
||||
FILE * udhcpc_fp;
|
||||
char *udhcpc_cmd = (char *)arg;
|
||||
|
||||
if (udhcpc_cmd == NULL)
|
||||
return NULL;
|
||||
|
||||
dbg_time("%s", udhcpc_cmd);
|
||||
udhcpc_fp = popen(udhcpc_cmd, "r");
|
||||
free(udhcpc_cmd);
|
||||
if (udhcpc_fp) {
|
||||
char buf[0xff];
|
||||
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
while((fgets(buf, sizeof(buf)-1, udhcpc_fp)) != NULL) {
|
||||
if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n'))
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
dbg_time("%s", buf);
|
||||
}
|
||||
|
||||
pclose(udhcpc_fp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void udhcpc_start_pcie(PROFILE_T *profile) {
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char sub_intf_name[100] = {0};
|
||||
int intf_id = 0;
|
||||
char shell_cmd[512];
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if (profile->muxid > 0x81)
|
||||
{
|
||||
intf_id = profile->muxid - 0x81;
|
||||
snprintf(sub_intf_name, sizeof(sub_intf_name) - 1, "%s.%d", ifname, intf_id);
|
||||
}
|
||||
|
||||
if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) {
|
||||
fibo_set_mtu(ifname, (profile->ipv4.Mtu));
|
||||
}
|
||||
|
||||
fibo_system("echo 1 > /sys/module/fibo_mhi/parameters/macaddr_check");
|
||||
|
||||
if (strcmp(ifname, profile->usbnet_adapter)) {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", profile->usbnet_adapter);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
// For IPv6, down & up will send protocol packets, and that's needed.
|
||||
if (profile->ipv6_flag && profile->muxid <= 0x81) {
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
//for bridge mode, only one public IP, so do udhcpc manually
|
||||
if (fibo_bridge_mode_detect(profile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do DHCP using busybox tools */
|
||||
{
|
||||
char udhcpc_cmd[128];
|
||||
pthread_attr_t udhcpc_thread_attr;
|
||||
pthread_t udhcpc_thread_id;
|
||||
|
||||
pthread_attr_init(&udhcpc_thread_attr);
|
||||
pthread_attr_setdetachstate(&udhcpc_thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
if (profile->ipv4.Address)
|
||||
{
|
||||
char v4add_str[32] = {0};
|
||||
char v4gw_str[32] = {0};
|
||||
char v4_netmask_str[32] = {0};
|
||||
uint32_t Address = ntohl(profile->ipv4.Address);
|
||||
uint32_t Gateway = ntohl(profile->ipv4.Gateway);
|
||||
uint32_t SubnetMask = ntohl(profile->ipv4.SubnetMask);
|
||||
inet_ntop(AF_INET, &Address, v4add_str, sizeof(v4add_str));
|
||||
inet_ntop(AF_INET, &Gateway, v4gw_str, sizeof(v4gw_str));
|
||||
inet_ntop(AF_INET, &SubnetMask, v4_netmask_str, sizeof(v4_netmask_str));
|
||||
|
||||
if (profile->muxid == 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s %s netmask %s", ifname, v4add_str, v4_netmask_str);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route add default gw %s dev %s", v4gw_str, ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
else if (profile->muxid > 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link add link %s name %s type vlan id %d", ifname, sub_intf_name, intf_id);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s %s netmask %s", sub_intf_name, v4add_str, v4_netmask_str);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (profile->ipv6.PrefixLengthIPAddr)
|
||||
{
|
||||
//module do not support DHCPv6, only support 'Router Solicit'
|
||||
//and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS
|
||||
const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
|
||||
int forward_fd = open(forward_file, O_RDONLY);
|
||||
if (forward_fd > 0) {
|
||||
char forward_state[2];
|
||||
read(forward_fd, forward_state, 2);
|
||||
if (forward_state[0] == '1') {
|
||||
dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file);
|
||||
}
|
||||
close(forward_fd);
|
||||
}
|
||||
|
||||
{
|
||||
char v6add_str[100] = {0};
|
||||
char v6gw_str[100] = {0};
|
||||
inet_ntop(AF_INET6, profile->ipv6.Address, v6add_str, sizeof(v6add_str));
|
||||
inet_ntop(AF_INET6, profile->ipv6.Gateway, v6gw_str, sizeof(v6gw_str));
|
||||
|
||||
if (profile->muxid == 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s add %s/%d", ifname, v6add_str, profile->ipv6.PrefixLengthIPAddr);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route -A inet6 add ::/0 gw %s dev %s", v6gw_str, ifname);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
else if (profile->muxid > 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link add link %s name %s type vlan id %d", ifname, sub_intf_name, intf_id);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s add %s/%d", sub_intf_name, v6add_str, profile->ipv6.PrefixLengthIPAddr);
|
||||
fibo_system(shell_cmd);
|
||||
/* start 2021-01-21 add by haopengfei to fix mantis 69056 */
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route -A inet6 add ::/0 gw %s dev %s", v6gw_str, sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
/* end 2021-01-21 add by haopengfei to fix mantis 69056 */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udhcpc_stop_pcie(PROFILE_T *profile) {
|
||||
char *ifname = profile->usbnet_adapter;
|
||||
char shell_cmd[128];
|
||||
char reset_ip[128];
|
||||
dbg_time("enter %s ", __func__);
|
||||
|
||||
if (profile->qmapnet_adapter) {
|
||||
ifname = profile->qmapnet_adapter;
|
||||
}
|
||||
|
||||
if (profile->muxid == 0x81)
|
||||
{
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s down", ifname);
|
||||
fibo_system(shell_cmd);
|
||||
snprintf(reset_ip, sizeof(reset_ip) - 1, "ifconfig %s 0.0.0.0", ifname);
|
||||
fibo_system(reset_ip);
|
||||
}
|
||||
else if (profile->muxid > 0x81)
|
||||
{
|
||||
char sub_intf_name[100];
|
||||
int intf_id = profile->muxid - 0x81;
|
||||
snprintf(sub_intf_name, sizeof(sub_intf_name) - 1, "%s.%d", ifname, intf_id);
|
||||
|
||||
snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link del link dev %s", sub_intf_name);
|
||||
fibo_system(shell_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "QMIThread.h"
|
||||
|
||||
#if defined(__STDC__)
|
||||
#include <stdarg.h>
|
||||
#define __V(x) x
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#define __V(x) (va_alist) va_dcl
|
||||
#define const
|
||||
#define volatile
|
||||
#endif
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#define is_bigendian() ((*(char *)&i) == 0)
|
||||
FILE *logfilefp = NULL;
|
||||
static pthread_mutex_t printfMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static char line[1024];
|
||||
const int i = 1;
|
||||
|
||||
// defined in atchannel.c
|
||||
static void setTimespecRelative(struct timespec *p_ts, long long msec)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, (struct timezone *)NULL);
|
||||
|
||||
/* what's really funny about this is that I know
|
||||
pthread_cond_timedwait just turns around and makes this
|
||||
a relative time again */
|
||||
p_ts->tv_sec = tv.tv_sec + (msec / 1000);
|
||||
p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L) * 1000L;
|
||||
}
|
||||
|
||||
int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
unsigned msecs)
|
||||
{
|
||||
if (msecs != 0) {
|
||||
struct timespec ts;
|
||||
setTimespecRelative(&ts, msecs);
|
||||
return pthread_cond_timedwait(cond, mutex, &ts);
|
||||
} else {
|
||||
return pthread_cond_wait(cond, mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_time(void)
|
||||
{
|
||||
static char time_buf[50];
|
||||
struct timeval tv;
|
||||
time_t time;
|
||||
suseconds_t millitm;
|
||||
struct tm *ti;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
time = tv.tv_sec;
|
||||
millitm = (tv.tv_usec + 500) / 1000;
|
||||
|
||||
if (millitm == 1000) {
|
||||
++time;
|
||||
millitm = 0;
|
||||
}
|
||||
|
||||
ti = localtime(&time);
|
||||
sprintf(time_buf, "[%02d-%02d_%02d:%02d:%02d:%03d]", ti->tm_mon + 1,
|
||||
ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm);
|
||||
return time_buf;
|
||||
}
|
||||
|
||||
void dbg_time(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
pthread_mutex_lock(&printfMutex);
|
||||
|
||||
snprintf(line, sizeof(line), "%s ", get_time());
|
||||
|
||||
vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, args);
|
||||
fprintf(stdout, "%s\n", line);
|
||||
|
||||
if (logfilefp) {
|
||||
fprintf(logfilefp, "%s\n", line);
|
||||
}
|
||||
fflush(logfilefp);
|
||||
pthread_mutex_unlock(&printfMutex);
|
||||
}
|
||||
|
||||
USHORT le16_to_cpu(USHORT v16)
|
||||
{
|
||||
USHORT tmp = v16;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v16);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[1];
|
||||
d[1] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
UINT le32_to_cpu(UINT v32)
|
||||
{
|
||||
UINT tmp = v32;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v32);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[3];
|
||||
d[1] = s[2];
|
||||
d[2] = s[1];
|
||||
d[3] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
USHORT cpu_to_le16(USHORT v16)
|
||||
{
|
||||
USHORT tmp = v16;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v16);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[1];
|
||||
d[1] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
UINT cpu_to_le32(UINT v32)
|
||||
{
|
||||
UINT tmp = v32;
|
||||
if (is_bigendian()) {
|
||||
unsigned char *s = (unsigned char *)(&v32);
|
||||
unsigned char *d = (unsigned char *)(&tmp);
|
||||
d[0] = s[3];
|
||||
d[1] = s[2];
|
||||
d[2] = s[1];
|
||||
d[3] = s[0];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct listnode {
|
||||
struct listnode *next;
|
||||
struct listnode *prev;
|
||||
};
|
||||
|
||||
#define node_to_item(node, container, member) \
|
||||
(container *)(((char *)(node)) - offsetof(container, member))
|
||||
|
||||
#define list_declare(name) \
|
||||
struct listnode name = { \
|
||||
.next = &name, \
|
||||
.prev = &name, \
|
||||
}
|
||||
|
||||
#define list_for_each(node, list) \
|
||||
for (node = (list)->next; node != (list); node = node->next)
|
||||
|
||||
#define list_for_each_reverse(node, list) \
|
||||
for (node = (list)->prev; node != (list); node = node->prev)
|
||||
void dbg_time(const char *fmt, ...);
|
||||
void list_init(struct listnode *list);
|
||||
void list_add_tail(struct listnode *list, struct listnode *item);
|
||||
void list_add_head(struct listnode *head, struct listnode *item);
|
||||
void list_remove(struct listnode *item);
|
||||
|
||||
#define list_empty(list) ((list) == (list)->next)
|
||||
#define list_head(list) ((list)->next)
|
||||
#define list_tail(list) ((list)->prev)
|
||||
|
||||
int epoll_register(int epoll_fd, int fd, unsigned int events);
|
||||
int epoll_deregister(int epoll_fd, int fd);
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=pcie_mhi_fb
|
||||
PKG_VERSION:=3.2
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/pcie_mhi_fb
|
||||
SUBMENU:=WWAN Support
|
||||
TITLE:=Kernel pcie driver for MHI device
|
||||
DEPENDS:=+pciids +pciutils +fibocom-dial
|
||||
FILES:=$(PKG_BUILD_DIR)/pcie_mhi_fb.ko
|
||||
AUTOLOAD:=$(call AutoLoad,90,pcie_mhi_fb)
|
||||
endef
|
||||
|
||||
define KernelPackage/pcie_mhi_fb/description
|
||||
Kernel module for register a custom pciemhi platform device.
|
||||
endef
|
||||
|
||||
MAKE_OPTS:= \
|
||||
ARCH="$(LINUX_KARCH)" \
|
||||
CROSS_COMPILE="$(TARGET_CROSS)" \
|
||||
CXXFLAGS="$(TARGET_CXXFLAGS)" \
|
||||
M="$(PKG_BUILD_DIR)" \
|
||||
$(EXTRA_KCONFIG)
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C "$(LINUX_DIR)" \
|
||||
$(MAKE_OPTS) \
|
||||
modules
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,pcie_mhi_fb))
|
||||
@@ -1,14 +0,0 @@
|
||||
menu "pcie mhi device Drivers"
|
||||
|
||||
config PCIE_MHI
|
||||
tristate "MHI dev net interface"
|
||||
help
|
||||
This modules enables userspace software clients to communicate
|
||||
with devices supporting the MHI protocol. Userspace clients
|
||||
may open the device nodes exposed by MHI UCI and perform
|
||||
read, write and ioctl operations to communicate with the
|
||||
attached device.
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
ccflags-y += -g -Wno-incompatible-pointer-types -Wno-unused-variable
|
||||
#ccflags-y += -DCONFIG_MHI_NETDEV_MBIM
|
||||
#obj-${CONFIG_PCIE_MHI} := fibo_mhi.o
|
||||
obj-m := fibo_mhi.o
|
||||
fibo_mhi-objs := core/mhi_init.o core/mhi_main.o core/mhi_pm.o core/mhi_boot.o core/mhi_dtr.o devices/mhi_netdev.o devices/mhi_uci.o controllers/mhi_qcom.o
|
||||
|
||||
PWD := $(shell pwd)
|
||||
ifeq ($(ARCH),)
|
||||
ARCH := $(shell uname -m)
|
||||
endif
|
||||
ifeq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE :=
|
||||
endif
|
||||
ifeq ($(KDIR),)
|
||||
KDIR := /lib/modules/$(shell uname -r)/build
|
||||
endif
|
||||
|
||||
|
||||
fibo_mhi: clean
|
||||
ifeq ($(findstring 86,$(ARCH)), 86)
|
||||
cp -f $(PWD)/controllers/mhi_qcom_x86.h $(PWD)/controllers/mhi_qcom.h
|
||||
else
|
||||
cp -f $(PWD)/controllers/mhi_qcom_arm.h $(PWD)/controllers/mhi_qcom.h
|
||||
endif
|
||||
#ln -sf makefile Makefile
|
||||
$(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
$(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) clean
|
||||
@@ -1,683 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/version.h>
|
||||
#include "../core/mhi.h"
|
||||
#include "mhi_qcom.h"
|
||||
|
||||
|
||||
#ifndef PCI_IRQ_MSI
|
||||
#define PCI_IRQ_MSI (1 << 1) /* Allow MSI interrupts */
|
||||
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 ))
|
||||
int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
|
||||
{
|
||||
int nvec = maxvec;
|
||||
int rc;
|
||||
|
||||
if (maxvec < minvec)
|
||||
return -ERANGE;
|
||||
|
||||
do {
|
||||
rc = pci_enable_msi_block(dev, nvec);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
} else if (rc > 0) {
|
||||
if (rc < minvec)
|
||||
return -ENOSPC;
|
||||
nvec = rc;
|
||||
}
|
||||
} while (rc);
|
||||
|
||||
return nvec;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int fibo_pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
|
||||
unsigned int max_vecs, unsigned int flags)
|
||||
{
|
||||
return pci_enable_msi_range(dev, min_vecs, max_vecs);
|
||||
}
|
||||
|
||||
static void fibo_pci_free_irq_vectors(struct pci_dev *dev)
|
||||
{
|
||||
pci_disable_msi(dev);
|
||||
}
|
||||
|
||||
static int fibo_pci_irq_vector(struct pci_dev *dev, unsigned int nr)
|
||||
{
|
||||
return dev->irq + nr;
|
||||
}
|
||||
#else
|
||||
static int fibo_pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
|
||||
unsigned int max_vecs, unsigned int flags)
|
||||
{
|
||||
return pci_alloc_irq_vectors(dev, min_vecs, max_vecs, flags);
|
||||
}
|
||||
|
||||
static void fibo_pci_free_irq_vectors(struct pci_dev *dev)
|
||||
{
|
||||
pci_free_irq_vectors(dev);
|
||||
}
|
||||
|
||||
static int fibo_pci_irq_vector(struct pci_dev *dev, unsigned int nr)
|
||||
{
|
||||
return pci_irq_vector(dev, nr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static struct pci_device_id mhi_pcie_device_id[] = {
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0300)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0301)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0302)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)},//SDX24
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0306)}, //SDX55
|
||||
{PCI_DEVICE(0x2C7C, 0x0512)},
|
||||
{PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)},
|
||||
{0},
|
||||
};
|
||||
|
||||
static struct pci_driver mhi_pcie_driver;
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
|
||||
fibo_pci_free_irq_vectors(pci_dev);
|
||||
iounmap(mhi_cntrl->regs);
|
||||
mhi_cntrl->regs = NULL;
|
||||
pci_clear_master(pci_dev);
|
||||
pci_release_region(pci_dev, mhi_dev->resn);
|
||||
pci_disable_device(pci_dev);
|
||||
}
|
||||
|
||||
static int mhi_init_pci_dev(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_dev *pci_dev = mhi_dev->pci_dev;
|
||||
int ret;
|
||||
resource_size_t start, len;
|
||||
int i;
|
||||
|
||||
mhi_dev->resn = MHI_PCI_BAR_NUM;
|
||||
ret = pci_assign_resource(pci_dev, mhi_dev->resn);
|
||||
if (ret) {
|
||||
MHI_ERR("Error assign pci resources, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pci_dev);
|
||||
if (ret) {
|
||||
MHI_ERR("Error enabling device, ret:%d\n", ret);
|
||||
goto error_enable_device;
|
||||
}
|
||||
|
||||
ret = pci_request_region(pci_dev, mhi_dev->resn, "mhi");
|
||||
if (ret) {
|
||||
MHI_ERR("Error pci_request_region, ret:%d\n", ret);
|
||||
goto error_request_region;
|
||||
}
|
||||
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
start = pci_resource_start(pci_dev, mhi_dev->resn);
|
||||
len = pci_resource_len(pci_dev, mhi_dev->resn);
|
||||
/*begin added by tony.du for mantis 0062018 on 2020-11-10*/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,6,0 ))
|
||||
mhi_cntrl->regs = ioremap_nocache(start, len);
|
||||
#else
|
||||
mhi_cntrl->regs = ioremap(start, len);
|
||||
#endif
|
||||
/*end added by tony.du for mantis 0062018 on 2020-11-10*/
|
||||
MHI_LOG("mhi_cntrl->regs = %p\n", mhi_cntrl->regs);
|
||||
if (!mhi_cntrl->regs) {
|
||||
MHI_ERR("Error ioremap region\n");
|
||||
goto error_ioremap;
|
||||
}
|
||||
|
||||
ret = fibo_pci_alloc_irq_vectors(pci_dev, 1, mhi_cntrl->msi_required, PCI_IRQ_MSI);
|
||||
if (IS_ERR_VALUE((ulong)ret) || ret < mhi_cntrl->msi_required) {
|
||||
if (ret == -ENOSPC) {
|
||||
}
|
||||
//imx_4.1.15_2.0.0_ga & DELL_OPTIPLEX_7010 only alloc one msi interrupt for one pcie device
|
||||
if (ret != 1) {
|
||||
MHI_ERR("Failed to enable MSI, ret=%d, msi_required=%d\n", ret, mhi_cntrl->msi_required);
|
||||
goto error_req_msi;
|
||||
}
|
||||
}
|
||||
|
||||
mhi_cntrl->msi_allocated = ret;
|
||||
MHI_LOG("msi_required = %d, msi_allocated = %d, msi_irq = %u\n", mhi_cntrl->msi_required, mhi_cntrl->msi_allocated, pci_dev->irq);
|
||||
|
||||
for (i = 0; i < mhi_cntrl->msi_allocated; i++) {
|
||||
mhi_cntrl->irq[i] = fibo_pci_irq_vector(pci_dev, i);
|
||||
if (mhi_cntrl->irq[i] < 0) {
|
||||
ret = mhi_cntrl->irq[i];
|
||||
goto error_get_irq_vec;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_get_irq_vec:
|
||||
fibo_pci_free_irq_vectors(pci_dev);
|
||||
|
||||
error_req_msi:
|
||||
iounmap(mhi_cntrl->regs);
|
||||
|
||||
error_ioremap:
|
||||
pci_clear_master(pci_dev);
|
||||
|
||||
error_request_region:
|
||||
pci_disable_device(pci_dev);
|
||||
|
||||
error_enable_device:
|
||||
pci_release_region(pci_dev, mhi_dev->resn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mhi_runtime_idle(struct device *dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
|
||||
MHI_LOG("Entered returning -EBUSY\n");
|
||||
|
||||
/*
|
||||
* RPM framework during runtime resume always calls
|
||||
* rpm_idle to see if device ready to suspend.
|
||||
* If dev.power usage_count count is 0, rpm fw will call
|
||||
* rpm_idle cb to see if device is ready to suspend.
|
||||
* if cb return 0, or cb not defined the framework will
|
||||
* assume device driver is ready to suspend;
|
||||
* therefore, fw will schedule runtime suspend.
|
||||
* In MHI power management, MHI host shall go to
|
||||
* runtime suspend only after entering MHI State M2, even if
|
||||
* usage count is 0. Return -EBUSY to disable automatic suspend.
|
||||
*/
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int mhi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
|
||||
MHI_LOG("Enter\n");
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
ret = mhi_pm_suspend(mhi_cntrl);
|
||||
if (ret) {
|
||||
MHI_LOG("Abort due to ret:%d\n", ret);
|
||||
goto exit_runtime_suspend;
|
||||
}
|
||||
|
||||
ret = mhi_arch_link_off(mhi_cntrl, true);
|
||||
if (ret)
|
||||
MHI_ERR("Failed to Turn off link ret:%d\n", ret);
|
||||
|
||||
exit_runtime_suspend:
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
MHI_LOG("Exited with ret:%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_runtime_resume(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Enter\n");
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
if (!mhi_dev->powered_on) {
|
||||
MHI_LOG("Not fully powered, return success\n");
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* turn on link */
|
||||
ret = mhi_arch_link_on(mhi_cntrl);
|
||||
if (ret)
|
||||
goto rpm_resume_exit;
|
||||
|
||||
/* enter M0 state */
|
||||
ret = mhi_pm_resume(mhi_cntrl);
|
||||
|
||||
rpm_resume_exit:
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
MHI_LOG("Exited with :%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_system_resume(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
|
||||
ret = mhi_runtime_resume(dev);
|
||||
if (ret) {
|
||||
MHI_ERR("Failed to resume link\n");
|
||||
} else {
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mhi_system_suspend(struct device *dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev);
|
||||
|
||||
MHI_LOG("Entered\n");
|
||||
|
||||
/* if rpm status still active then force suspend */
|
||||
if (!pm_runtime_status_suspended(dev))
|
||||
return mhi_runtime_suspend(dev);
|
||||
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
MHI_LOG("Exit\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* checks if link is down */
|
||||
static int mhi_link_status(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
u16 dev_id;
|
||||
int ret;
|
||||
|
||||
/* try reading device id, if dev id don't match, link is down */
|
||||
ret = pci_read_config_word(mhi_dev->pci_dev, PCI_DEVICE_ID, &dev_id);
|
||||
|
||||
return (ret || dev_id != mhi_cntrl->dev_id) ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int mhi_runtime_get(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct device *dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
return pm_runtime_get(dev);
|
||||
}
|
||||
|
||||
static void mhi_runtime_put(struct mhi_controller *mhi_cntrl, void *priv)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct device *dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
pm_runtime_put_noidle(dev);
|
||||
}
|
||||
|
||||
static void mhi_status_cb(struct mhi_controller *mhi_cntrl,
|
||||
void *priv,
|
||||
enum MHI_CB reason)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = priv;
|
||||
struct device *dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
if (reason == MHI_CB_IDLE) {
|
||||
MHI_LOG("Schedule runtime suspend 1\n");
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_request_autosuspend(dev);
|
||||
}
|
||||
}
|
||||
|
||||
int mhi_debugfs_trigger_m0(void *data, u64 val)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = data;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Trigger M3 Exit\n");
|
||||
pm_runtime_get(&mhi_dev->pci_dev->dev);
|
||||
pm_runtime_put(&mhi_dev->pci_dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mhi_debugfs_trigger_m3(void *data, u64 val)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = data;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Trigger M3 Entry\n");
|
||||
pm_runtime_mark_last_busy(&mhi_dev->pci_dev->dev);
|
||||
pm_request_autosuspend(&mhi_dev->pci_dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m0_fops, NULL,
|
||||
mhi_debugfs_trigger_m0, "%llu\n");
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m3_fops, NULL,
|
||||
mhi_debugfs_trigger_m3, "%llu\n");
|
||||
|
||||
static int mhi_init_debugfs_trigger_go(void *data, u64 val)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = data;
|
||||
|
||||
MHI_LOG("Trigger power up sequence\n");
|
||||
|
||||
mhi_async_power_up(mhi_cntrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(mhi_init_debugfs_trigger_go_fops, NULL,
|
||||
mhi_init_debugfs_trigger_go, "%llu\n");
|
||||
|
||||
|
||||
int mhi_init_debugfs_debug_show(struct seq_file *m, void *d)
|
||||
{
|
||||
seq_puts(m, "Enable debug mode to debug external soc\n");
|
||||
seq_puts(m,
|
||||
"Usage: echo 'devid,timeout,domain,smmu_cfg' > debug_mode\n");
|
||||
seq_puts(m, "No spaces between parameters\n");
|
||||
seq_puts(m, "\t1. devid : 0 or pci device id to register\n");
|
||||
seq_puts(m, "\t2. timeout: mhi cmd/state transition timeout\n");
|
||||
seq_puts(m, "\t3. domain: Rootcomplex\n");
|
||||
seq_puts(m, "\t4. smmu_cfg: smmu configuration mask:\n");
|
||||
seq_puts(m, "\t\t- BIT0: ATTACH\n");
|
||||
seq_puts(m, "\t\t- BIT1: S1 BYPASS\n");
|
||||
seq_puts(m, "\t\t-BIT2: FAST_MAP\n");
|
||||
seq_puts(m, "\t\t-BIT3: ATOMIC\n");
|
||||
seq_puts(m, "\t\t-BIT4: FORCE_COHERENT\n");
|
||||
seq_puts(m, "\t\t-BIT5: GEOMETRY\n");
|
||||
seq_puts(m, "\tAll timeout are in ms, enter 0 to keep default\n");
|
||||
seq_puts(m, "Examples inputs: '0x307,10000'\n");
|
||||
seq_puts(m, "\techo '0,10000,1'\n");
|
||||
seq_puts(m, "\techo '0x307,10000,0,0x3d'\n");
|
||||
seq_puts(m, "firmware image name will be changed to debug.mbn\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mhi_init_debugfs_debug_open(struct inode *node, struct file *file)
|
||||
{
|
||||
return single_open(file, mhi_init_debugfs_debug_show, NULL);
|
||||
}
|
||||
|
||||
static ssize_t mhi_init_debugfs_debug_write(struct file *fp,
|
||||
const char __user *ubuf,
|
||||
size_t count,
|
||||
loff_t *pos)
|
||||
{
|
||||
char *buf = kmalloc(count + 1, GFP_KERNEL);
|
||||
/* #,devid,timeout,domain,smmu-cfg */
|
||||
int args[5] = {0};
|
||||
static char const *dbg_fw = "debug.mbn";
|
||||
int ret;
|
||||
struct mhi_controller *mhi_cntrl = fp->f_inode->i_private;
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
struct pci_device_id *id;
|
||||
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = copy_from_user(buf, ubuf, count);
|
||||
if (ret)
|
||||
goto error_read;
|
||||
buf[count] = 0;
|
||||
get_options(buf, ARRAY_SIZE(args), args);
|
||||
kfree(buf);
|
||||
|
||||
/* override default parameters */
|
||||
mhi_cntrl->fw_image = dbg_fw;
|
||||
mhi_cntrl->edl_image = dbg_fw;
|
||||
|
||||
if (args[0] >= 2 && args[2])
|
||||
mhi_cntrl->timeout_ms = args[2];
|
||||
|
||||
if (args[0] >= 3 && args[3])
|
||||
mhi_cntrl->domain = args[3];
|
||||
|
||||
if (args[0] >= 4 && args[4])
|
||||
mhi_dev->smmu_cfg = args[4];
|
||||
|
||||
/* If it's a new device id register it */
|
||||
if (args[0] && args[1]) {
|
||||
/* find the debug_id and overwrite it */
|
||||
for (id = mhi_pcie_device_id; id->vendor; id++)
|
||||
if (id->device == MHI_PCIE_DEBUG_ID) {
|
||||
id->device = args[1];
|
||||
pci_unregister_driver(&mhi_pcie_driver);
|
||||
ret = pci_register_driver(&mhi_pcie_driver);
|
||||
}
|
||||
}
|
||||
|
||||
mhi_dev->debug_mode = true;
|
||||
debugfs_create_file("go", 0444, mhi_cntrl->parent, mhi_cntrl,
|
||||
&mhi_init_debugfs_trigger_go_fops);
|
||||
pr_info(
|
||||
"%s: ret:%d pcidev:0x%x smm_cfg:%u timeout:%u\n",
|
||||
__func__, ret, args[1], mhi_dev->smmu_cfg,
|
||||
mhi_cntrl->timeout_ms);
|
||||
return count;
|
||||
|
||||
error_read:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations debugfs_debug_ops = {
|
||||
.open = mhi_init_debugfs_debug_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
.write = mhi_init_debugfs_debug_write,
|
||||
};
|
||||
|
||||
static struct mhi_controller * mhi_platform_probe(struct pci_dev *pci_dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
struct mhi_dev *mhi_dev;
|
||||
u64 addr_win[2];
|
||||
int ret;
|
||||
|
||||
mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev));
|
||||
if (!mhi_cntrl) {
|
||||
pr_err("mhi_alloc_controller fail\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->dev_id = pci_dev->device;
|
||||
mhi_cntrl->domain = pci_domain_nr(pci_dev->bus);
|
||||
mhi_cntrl->bus = pci_dev->bus->number;
|
||||
mhi_cntrl->slot = PCI_SLOT(pci_dev->devfn);
|
||||
mhi_dev->smmu_cfg = 0;
|
||||
|
||||
addr_win[0] = 0;
|
||||
addr_win[1] = 0xFFFFFFFFF; //16GB
|
||||
|
||||
mhi_cntrl->iova_start = addr_win[0];
|
||||
mhi_cntrl->iova_stop = addr_win[1];
|
||||
|
||||
mhi_dev->pci_dev = pci_dev;
|
||||
mhi_cntrl->pci_dev = pci_dev;
|
||||
|
||||
/* setup power management apis */
|
||||
mhi_cntrl->status_cb = mhi_status_cb;
|
||||
mhi_cntrl->runtime_get = mhi_runtime_get;
|
||||
mhi_cntrl->runtime_put = mhi_runtime_put;
|
||||
mhi_cntrl->link_status = mhi_link_status;
|
||||
|
||||
ret = mhi_arch_platform_init(mhi_dev);
|
||||
if (ret)
|
||||
goto error_probe;
|
||||
|
||||
ret = mhi_register_mhi_controller(mhi_cntrl);
|
||||
if (ret)
|
||||
goto error_register;
|
||||
|
||||
if (mhi_cntrl->parent)
|
||||
debugfs_create_file("debug_mode", 0444, mhi_cntrl->parent,
|
||||
mhi_cntrl, &debugfs_debug_ops);
|
||||
|
||||
return mhi_cntrl;
|
||||
|
||||
error_register:
|
||||
mhi_arch_platform_deinit(mhi_dev);
|
||||
|
||||
error_probe:
|
||||
mhi_free_controller(mhi_cntrl);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = NULL;
|
||||
u32 domain = pci_domain_nr(pci_dev->bus);
|
||||
u32 bus = pci_dev->bus->number;
|
||||
u32 slot = PCI_SLOT(pci_dev->devfn);
|
||||
struct mhi_dev *mhi_dev;
|
||||
int ret;
|
||||
|
||||
pr_err("INFO:%s pci_dev->name = %s, domain=%d, bus=%d, slot=%d, vendor=%04X, device=%04X\n",
|
||||
__func__, dev_name(&pci_dev->dev), domain, bus, slot, pci_dev->vendor, pci_dev->device);
|
||||
|
||||
mhi_cntrl = mhi_platform_probe(pci_dev);
|
||||
if (!mhi_cntrl) {
|
||||
pr_err("mhi_platform_probe fail\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
mhi_cntrl->dev_id = pci_dev->device;
|
||||
mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
mhi_dev->pci_dev = pci_dev;
|
||||
mhi_dev->powered_on = true;
|
||||
|
||||
ret = mhi_arch_pcie_init(mhi_cntrl);
|
||||
if (ret) {
|
||||
MHI_ERR("Error mhi_arch_pcie_init, ret:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mhi_arch_iommu_init(mhi_cntrl);
|
||||
if (ret) {
|
||||
MHI_ERR("Error mhi_arch_iommu_init, ret:%d\n", ret);
|
||||
goto error_iommu_init;
|
||||
}
|
||||
|
||||
ret = mhi_init_pci_dev(mhi_cntrl);
|
||||
if (ret) {
|
||||
MHI_ERR("Error mhi_init_pci_dev, ret:%d\n", ret);
|
||||
goto error_init_pci;
|
||||
}
|
||||
|
||||
/* start power up sequence if not in debug mode */
|
||||
if (!mhi_dev->debug_mode) {
|
||||
ret = mhi_async_power_up(mhi_cntrl);
|
||||
if (ret) {
|
||||
MHI_ERR("Error mhi_async_power_up, ret:%d\n", ret);
|
||||
goto error_power_up;
|
||||
}
|
||||
}
|
||||
|
||||
if (mhi_cntrl->dentry) {
|
||||
debugfs_create_file("m0", 0444, mhi_cntrl->dentry, mhi_cntrl,
|
||||
&debugfs_trigger_m0_fops);
|
||||
debugfs_create_file("m3", 0444, mhi_cntrl->dentry, mhi_cntrl,
|
||||
&debugfs_trigger_m3_fops);
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pci_dev->dev, mhi_cntrl);
|
||||
MHI_LOG("Return successful\n");
|
||||
|
||||
return 0;
|
||||
|
||||
error_power_up:
|
||||
mhi_deinit_pci_dev(mhi_cntrl);
|
||||
|
||||
error_init_pci:
|
||||
mhi_arch_iommu_deinit(mhi_cntrl);
|
||||
|
||||
error_iommu_init:
|
||||
mhi_arch_pcie_deinit(mhi_cntrl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mhi_pci_remove(struct pci_dev *pci_dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = (struct mhi_controller *)dev_get_drvdata(&pci_dev->dev);
|
||||
|
||||
if (mhi_cntrl && mhi_cntrl->pci_dev == pci_dev) {
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
MHI_LOG("%s\n", dev_name(&pci_dev->dev));
|
||||
if (!mhi_dev->debug_mode) {
|
||||
mhi_power_down(mhi_cntrl, 1);
|
||||
}
|
||||
mhi_deinit_pci_dev(mhi_cntrl);
|
||||
mhi_arch_iommu_deinit(mhi_cntrl);
|
||||
mhi_arch_pcie_deinit(mhi_cntrl);
|
||||
mhi_unregister_mhi_controller(mhi_cntrl);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(mhi_runtime_suspend,
|
||||
mhi_runtime_resume,
|
||||
mhi_runtime_idle)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(mhi_system_suspend, mhi_system_resume)
|
||||
};
|
||||
|
||||
static struct pci_driver mhi_pcie_driver = {
|
||||
.name = "mhi",
|
||||
.id_table = mhi_pcie_device_id,
|
||||
.probe = mhi_pci_probe,
|
||||
.remove = mhi_pci_remove,
|
||||
.driver = {
|
||||
.pm = &pm_ops
|
||||
}
|
||||
};
|
||||
|
||||
int __init mhi_controller_qcom_init(void)
|
||||
{
|
||||
return pci_register_driver(&mhi_pcie_driver);
|
||||
};
|
||||
|
||||
void mhi_controller_qcom_exit(void)
|
||||
{
|
||||
pr_err("INFO:%s enter\n", __func__);
|
||||
pci_unregister_driver(&mhi_pcie_driver);
|
||||
pr_err("INFO:%s exit\n", __func__);
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef _MHI_QCOM_
|
||||
#define _MHI_QCOM_
|
||||
|
||||
/* iova cfg bitmask */
|
||||
#define MHI_SMMU_ATTACH BIT(0)
|
||||
#define MHI_SMMU_S1_BYPASS BIT(1)
|
||||
#define MHI_SMMU_FAST BIT(2)
|
||||
#define MHI_SMMU_ATOMIC BIT(3)
|
||||
#define MHI_SMMU_FORCE_COHERENT BIT(4)
|
||||
|
||||
#define MHI_PCIE_VENDOR_ID (0x17cb)
|
||||
#define MHI_PCIE_DEBUG_ID (0xffff)
|
||||
#define MHI_RPM_SUSPEND_TMR_MS (3000)
|
||||
#define MHI_PCI_BAR_NUM (0)
|
||||
|
||||
struct mhi_dev {
|
||||
struct pci_dev *pci_dev;
|
||||
u32 smmu_cfg;
|
||||
int resn;
|
||||
void *arch_info;
|
||||
bool powered_on;
|
||||
bool debug_mode;
|
||||
};
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id);
|
||||
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 ))
|
||||
static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
|
||||
{
|
||||
int rc = dma_set_mask(dev, mask);
|
||||
if (rc == 0)
|
||||
dma_set_coherent_mask(dev, mask);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64));
|
||||
}
|
||||
|
||||
static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl,
|
||||
bool graceful)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MHI_QCOM_ */
|
||||
@@ -1,92 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef _MHI_QCOM_
|
||||
#define _MHI_QCOM_
|
||||
|
||||
/* iova cfg bitmask */
|
||||
#define MHI_SMMU_ATTACH BIT(0)
|
||||
#define MHI_SMMU_S1_BYPASS BIT(1)
|
||||
#define MHI_SMMU_FAST BIT(2)
|
||||
#define MHI_SMMU_ATOMIC BIT(3)
|
||||
#define MHI_SMMU_FORCE_COHERENT BIT(4)
|
||||
|
||||
#define MHI_PCIE_VENDOR_ID (0x17cb)
|
||||
#define MHI_PCIE_DEBUG_ID (0xffff)
|
||||
#define MHI_RPM_SUSPEND_TMR_MS (3000)
|
||||
#define MHI_PCI_BAR_NUM (0)
|
||||
|
||||
struct mhi_dev {
|
||||
struct pci_dev *pci_dev;
|
||||
u32 smmu_cfg;
|
||||
int resn;
|
||||
void *arch_info;
|
||||
bool powered_on;
|
||||
bool debug_mode;
|
||||
};
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id);
|
||||
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 ))
|
||||
static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
|
||||
{
|
||||
int rc = dma_set_mask(dev, mask);
|
||||
if (rc == 0)
|
||||
dma_set_coherent_mask(dev, mask);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64));
|
||||
}
|
||||
|
||||
static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl,
|
||||
bool graceful)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MHI_QCOM_ */
|
||||
@@ -1,92 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef _MHI_QCOM_
|
||||
#define _MHI_QCOM_
|
||||
|
||||
/* iova cfg bitmask */
|
||||
#define MHI_SMMU_ATTACH BIT(0)
|
||||
#define MHI_SMMU_S1_BYPASS BIT(1)
|
||||
#define MHI_SMMU_FAST BIT(2)
|
||||
#define MHI_SMMU_ATOMIC BIT(3)
|
||||
#define MHI_SMMU_FORCE_COHERENT BIT(4)
|
||||
|
||||
#define MHI_PCIE_VENDOR_ID (0x17cb)
|
||||
#define MHI_PCIE_DEBUG_ID (0xffff)
|
||||
#define MHI_RPM_SUSPEND_TMR_MS (3000)
|
||||
#define MHI_PCI_BAR_NUM (0)
|
||||
|
||||
struct mhi_dev {
|
||||
struct pci_dev *pci_dev;
|
||||
u32 smmu_cfg;
|
||||
int resn;
|
||||
void *arch_info;
|
||||
bool powered_on;
|
||||
bool debug_mode;
|
||||
};
|
||||
|
||||
void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *device_id);
|
||||
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 ))
|
||||
static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
|
||||
{
|
||||
int rc = dma_set_mask(dev, mask);
|
||||
if (rc == 0)
|
||||
dma_set_coherent_mask(dev, mask);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
|
||||
|
||||
return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(32));
|
||||
}
|
||||
|
||||
static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl,
|
||||
bool graceful)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MHI_QCOM_ */
|
||||
@@ -1,891 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef _MHI_H_
|
||||
#define _MHI_H_
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
|
||||
typedef u64 uint64;
|
||||
typedef u32 uint32;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MHI_CLIENT_LOOPBACK_OUT = 0,
|
||||
MHI_CLIENT_LOOPBACK_IN = 1,
|
||||
MHI_CLIENT_SAHARA_OUT = 2,
|
||||
MHI_CLIENT_SAHARA_IN = 3,
|
||||
MHI_CLIENT_DIAG_OUT = 4,
|
||||
MHI_CLIENT_DIAG_IN = 5,
|
||||
MHI_CLIENT_SSR_OUT = 6,
|
||||
MHI_CLIENT_SSR_IN = 7,
|
||||
MHI_CLIENT_QDSS_OUT = 8,
|
||||
MHI_CLIENT_QDSS_IN = 9,
|
||||
MHI_CLIENT_EFS_OUT = 10,
|
||||
MHI_CLIENT_EFS_IN = 11,
|
||||
MHI_CLIENT_MBIM_OUT = 12,
|
||||
MHI_CLIENT_MBIM_IN = 13,
|
||||
MHI_CLIENT_QMI_OUT = 14,
|
||||
MHI_CLIENT_QMI_IN = 15,
|
||||
MHI_CLIENT_QMI_2_OUT = 16,
|
||||
MHI_CLIENT_QMI_2_IN = 17,
|
||||
MHI_CLIENT_IP_CTRL_1_OUT = 18,
|
||||
MHI_CLIENT_IP_CTRL_1_IN = 19,
|
||||
MHI_CLIENT_IPCR_OUT = 20,
|
||||
MHI_CLIENT_IPCR_IN = 21,
|
||||
MHI_CLIENT_TEST_FW_OUT = 22,
|
||||
MHI_CLIENT_TEST_FW_IN = 23,
|
||||
MHI_CLIENT_RESERVED_0 = 24,
|
||||
MHI_CLIENT_BOOT_LOG_IN = 25,
|
||||
MHI_CLIENT_DCI_OUT = 26,
|
||||
MHI_CLIENT_DCI_IN = 27,
|
||||
MHI_CLIENT_QBI_OUT = 28,
|
||||
MHI_CLIENT_QBI_IN = 29,
|
||||
MHI_CLIENT_RESERVED_1_LOWER = 30,
|
||||
MHI_CLIENT_RESERVED_1_UPPER = 31,
|
||||
MHI_CLIENT_DUN_OUT = 32,
|
||||
MHI_CLIENT_DUN_IN = 33,
|
||||
MHI_CLIENT_EDL_OUT = 34,
|
||||
MHI_CLIENT_EDL_IN = 35,
|
||||
MHI_CLIENT_ADB_FB_OUT = 36,
|
||||
MHI_CLIENT_ADB_FB_IN = 37,
|
||||
MHI_CLIENT_RESERVED_2_LOWER = 38,
|
||||
MHI_CLIENT_RESERVED_2_UPPER = 41,
|
||||
MHI_CLIENT_CSVT_OUT = 42,
|
||||
MHI_CLIENT_CSVT_IN = 43,
|
||||
MHI_CLIENT_SMCT_OUT = 44,
|
||||
MHI_CLIENT_SMCT_IN = 45,
|
||||
MHI_CLIENT_IP_SW_0_OUT = 46,
|
||||
MHI_CLIENT_IP_SW_0_IN = 47,
|
||||
MHI_CLIENT_IP_SW_1_OUT = 48,
|
||||
MHI_CLIENT_IP_SW_1_IN = 49,
|
||||
MHI_CLIENT_GNSS_OUT = 50,
|
||||
MHI_CLIENT_GNSS_IN = 51,
|
||||
MHI_CLIENT_AUDIO_OUT = 52,
|
||||
MHI_CLIENT_AUDIO_IN = 53,
|
||||
MHI_CLIENT_RESERVED_3_LOWER = 54,
|
||||
MHI_CLIENT_RESERVED_3_UPPER = 59,
|
||||
MHI_CLIENT_TEST_0_OUT = 60,
|
||||
MHI_CLIENT_TEST_0_IN = 61,
|
||||
MHI_CLIENT_TEST_1_OUT = 62,
|
||||
MHI_CLIENT_TEST_1_IN = 63,
|
||||
MHI_CLIENT_TEST_2_OUT = 64,
|
||||
MHI_CLIENT_TEST_2_IN = 65,
|
||||
MHI_CLIENT_TEST_3_OUT = 66,
|
||||
MHI_CLIENT_TEST_3_IN = 67,
|
||||
MHI_CLIENT_RESERVED_4_LOWER = 68,
|
||||
MHI_CLIENT_RESERVED_4_UPPER = 91,
|
||||
MHI_CLIENT_OEM_0_OUT = 92,
|
||||
MHI_CLIENT_OEM_0_IN = 93,
|
||||
MHI_CLIENT_OEM_1_OUT = 94,
|
||||
MHI_CLIENT_OEM_1_IN = 95,
|
||||
MHI_CLIENT_OEM_2_OUT = 96,
|
||||
MHI_CLIENT_OEM_2_IN = 97,
|
||||
MHI_CLIENT_OEM_3_OUT = 98,
|
||||
MHI_CLIENT_OEM_3_IN = 99,
|
||||
MHI_CLIENT_IP_HW_0_OUT = 100,
|
||||
MHI_CLIENT_IP_HW_0_IN = 101,
|
||||
MHI_CLIENT_ADPL = 102,
|
||||
MHI_CLIENT_RESERVED_5_LOWER = 103,
|
||||
MHI_CLIENT_RESERVED_5_UPPER = 127,
|
||||
MHI_MAX_CHANNELS = 128
|
||||
}MHI_CLIENT_CHANNEL_TYPE;
|
||||
|
||||
#define MHI_VERSION 0x01000000
|
||||
#define MHIREGLEN_VALUE 0x100 /* **** WRONG VALUE *** */
|
||||
#define MHI_MSI_INDEX 1
|
||||
#define MAX_NUM_MHI_DEVICES 1
|
||||
#define NUM_MHI_XFER_RINGS 128
|
||||
#define NUM_MHI_EVT_RINGS 3
|
||||
#define PRIMARY_EVENT_RING 0
|
||||
#define IPA_OUT_EVENT_RING 1
|
||||
#define IPA_IN_EVENT_RING 2
|
||||
#define NUM_MHI_XFER_RING_ELEMENTS 16
|
||||
#define NUM_MHI_EVT_RING_ELEMENTS 256
|
||||
#define NUM_MHI_IPA_OUT_EVT_RING_ELEMENTS 2048
|
||||
#define NUM_MHI_IPA_IN_EVT_RING_ELEMENTS 1024
|
||||
#define NUM_MHI_IPA_IN_RING_ELEMENTS 256
|
||||
#define NUM_MHI_IPA_OUT_RING_ELEMENTS 256
|
||||
#define NUM_MHI_DIAG_IN_RING_ELEMENTS 128
|
||||
#define NUM_MHI_CHAN_RING_ELEMENTS 8
|
||||
#define MHI_EVT_CMD_QUEUE_SIZE 160
|
||||
#define MHI_EVT_STATE_QUEUE_SIZE 128
|
||||
#define MHI_EVT_XFER_QUEUE_SIZE 1024
|
||||
#define MHI_ALIGN_4BYTE_OFFSET 0x3
|
||||
#define MHI_ALIGN_4K_OFFSET 0xFFF
|
||||
#define MAX_TRB_DATA_SIZE 0xFFFF
|
||||
#define RESERVED_VALUE_64 0xFFFFFFFFFFFFFFFF
|
||||
#define RESERVED_VALUE 0xFFFFFFFF
|
||||
#define PCIE_LINK_DOWN 0xFFFFFFFF
|
||||
#define SECONDS 1000
|
||||
#define MINUTES 60000
|
||||
|
||||
#define MHI_FILE_MHI 0x4D4849
|
||||
#define MHI_FILE_INIT 0x494E4954
|
||||
#define MHI_FILE_MSI 0x4D5349
|
||||
#define MHI_FILE_OS 0x4F53
|
||||
#define MHI_FILE_SM 0x534D
|
||||
#define MHI_FILE_THREADS 0x54485245
|
||||
#define MHI_FILE_TRANSFER 0x5452414E
|
||||
#define MHI_FILE_UTILS 0x5554494C
|
||||
|
||||
|
||||
#define MHI_ER_PRIORITY_HIGH 0
|
||||
#define MHI_ER_PRIORITY_MEDIUM 1
|
||||
#define MHI_ER_PRIORITY_SPECIAL 2
|
||||
|
||||
#undef FALSE
|
||||
#undef TRUE
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
typedef struct MHI_DEV_CTXT MHI_DEV_CTXT;
|
||||
typedef struct PCI_CORE_INFO PCI_CORE_INFO;
|
||||
typedef struct PCIE_DEV_INFO PCIE_DEV_INFO;
|
||||
|
||||
/* Memory Segment Properties */
|
||||
typedef struct _MHI_MEM_PROPS
|
||||
{
|
||||
uint64 VirtAligned;
|
||||
uint64 VirtUnaligned;
|
||||
uint64 PhysAligned;
|
||||
uint64 PhysUnaligned;
|
||||
uint64 Size;
|
||||
void *Handle;
|
||||
}MHI_MEM_PROPS, *PMHI_MEM_PROPS;
|
||||
|
||||
/* Device Power State Type */
|
||||
typedef enum
|
||||
{
|
||||
POWER_DEVICE_INVALID = 0,
|
||||
POWER_DEVICE_D0 = 1,
|
||||
POWER_DEVICE_D1 = 2,
|
||||
POWER_DEVICE_D2 = 3,
|
||||
POWER_DEVICE_D3 = 4,
|
||||
POWER_DEVICE_D3FINAL = 5, // System shutting down
|
||||
POWER_DEVICE_HIBARNATION = 6, // Entering system state S4
|
||||
POWER_DEVICE_MAX = 7
|
||||
}PWR_STATE_TYPE;
|
||||
|
||||
/* Channel State */
|
||||
typedef enum
|
||||
{
|
||||
CHAN_STATE_DISABLED = 0,
|
||||
CHAN_STATE_ENABLED = 1,
|
||||
CHAN_STATE_RUNNING = 2,
|
||||
CHAN_STATE_SUSPENDED = 3,
|
||||
CHAN_STATE_STOPPED = 4,
|
||||
CHAN_STATE_ERROR = 5,
|
||||
|
||||
CHAN_STATE_OTHER = RESERVED_VALUE
|
||||
}CHAN_STATE_TYPE;
|
||||
|
||||
/* Channel Type */
|
||||
typedef enum
|
||||
{
|
||||
INVALID_CHAN = 0,
|
||||
OUTBOUND_CHAN = 1,
|
||||
INBOUND_CHAN = 2,
|
||||
|
||||
OTHER_CHAN = RESERVED_VALUE
|
||||
}CHAN_TYPE;
|
||||
|
||||
/* Ring Type */
|
||||
typedef enum
|
||||
{
|
||||
CMD_RING = 0,
|
||||
XFER_RING = 1,
|
||||
EVT_RING = 2,
|
||||
}MHI_RING_TYPE;
|
||||
|
||||
/* Event Ring */
|
||||
typedef enum
|
||||
{
|
||||
EVT_RING_INVALID = 0x0,
|
||||
EVT_RING_VALID = 0x1,
|
||||
EVT_RING_RESERVED = RESERVED_VALUE
|
||||
}MHI_EVENT_RING_TYPE;
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
/* MHI Ring Context */
|
||||
typedef /*_ALIGN(1)*/ struct _MHI_RING_CTXT_TYPE
|
||||
{
|
||||
uint32 Info;
|
||||
uint32 Type;
|
||||
uint32 Index;
|
||||
uint64 Base;
|
||||
uint64 Length;
|
||||
volatile uint64 RP;
|
||||
uint64 WP;
|
||||
}MHI_RING_CTXT_TYPE, *PMHI_RING_CTXT_TYPE;
|
||||
|
||||
/* MHI Ring Element */
|
||||
typedef /*_ALIGN(1)*/ struct _MHI_ELEMENT_TYPE
|
||||
{
|
||||
uint64 Ptr;
|
||||
uint32 Status;
|
||||
uint32 Control;
|
||||
}MHI_ELEMENT_TYPE, *PMHI_ELEMENT_TYPE;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* Command Ring Element Type */
|
||||
typedef enum
|
||||
{
|
||||
CMD_NONE = 0,
|
||||
CMD_NOOP = 1,
|
||||
CMD_RESET_CHAN = 16,
|
||||
CMD_STOP_CHAN = 17,
|
||||
CMD_START_CHAN = 18,
|
||||
CMD_CANCEL_CHAN_XFERS = 21
|
||||
}MHI_CMD_TYPE;
|
||||
|
||||
/* Event Ring Element Type */
|
||||
typedef enum
|
||||
{
|
||||
STATE_CHANGE_EVT = 32,
|
||||
CMD_COMPLETION_EVT = 33,
|
||||
XFER_COMPLETION_EVT = 34,
|
||||
EE_STATE_CHANGE_EVT = 64
|
||||
} MHI_EVT_TYPE;
|
||||
|
||||
/* Ring Status Type */
|
||||
typedef enum
|
||||
{
|
||||
RING_EMPTY = 0,
|
||||
RING_FULL = 1,
|
||||
RING_QUEUED = 2,
|
||||
} MHI_RING_STATUS_TYPE;
|
||||
|
||||
/* XFER Ring Element Type */
|
||||
#define XFER_RING_ELEMENT_TYPE 2
|
||||
|
||||
/* Event Ring Completion Status */
|
||||
typedef enum
|
||||
{
|
||||
EVT_COMPLETION_INVALID = 0,
|
||||
EVT_COMPLETION_SUCCESS = 1,
|
||||
EVT_COMPLETION_EOT = 2,
|
||||
EVT_COMPLETION_OVERFLOW = 3,
|
||||
EVT_COMPLETION_EOB = 4,
|
||||
EVT_COMPLETION_OOB = 5, /* Out-Of-Buffer */
|
||||
EVT_COMPLETION_DB_MODE = 6,
|
||||
EVT_COMPLETION_UNDEFINED = 16,
|
||||
EVT_COMPLETION_MALFORMED = 17,
|
||||
|
||||
EVT_COMPLETION_OTHER = RESERVED_VALUE
|
||||
}EVT_COMPLETION_STATUS_TYPE;
|
||||
|
||||
/* *********************************************************************************************** */
|
||||
/* Macros */
|
||||
/* *********************************************************************************************** */
|
||||
#define ADVANCE_RING_PTR(RingCtxt, Ptr, Size) \
|
||||
*Ptr = ((*Ptr - RingCtxt->Base)/sizeof(MHI_ELEMENT_TYPE) == (Size - 1))? \
|
||||
RingCtxt->Base: (*Ptr + sizeof(MHI_ELEMENT_TYPE))
|
||||
|
||||
#define GET_VIRT_ADDR(MhiCtxt, PhysAddr) \
|
||||
((MhiCtxt)->CtrlSegProps.VirtAligned + ((PhysAddr) - (MhiCtxt)->CtrlSegProps.PhysAligned)) \
|
||||
|
||||
#define GET_PHYS_ADDR(MhiCtxt, VirtAddr) \
|
||||
((MhiCtxt)->CtrlSegProps.PhysAligned + ((VirtAddr) - (MhiCtxt)->CtrlSegProps.VirtAligned)) \
|
||||
|
||||
#define GET_RING_ELEMENT_INDEX(RingBase, Element) \
|
||||
(((Element) - (RingBase))/sizeof(MHI_ELEMENT_TYPE))
|
||||
|
||||
#define VALID_RING_PTR(Ring, Ptr) \
|
||||
(((Ptr) >= (Ring)->Base) && \
|
||||
((Ptr) <= ((Ring)->Base + (Ring)->Length - sizeof(MHI_ELEMENT_TYPE))))
|
||||
|
||||
#define CHAN_INBOUND(_x) ((_x)%2)
|
||||
|
||||
#define CHAN_SBL(_x) (((_x) == MHI_CLIENT_SAHARA_OUT) || \
|
||||
((_x) == MHI_CLIENT_SAHARA_IN) || \
|
||||
((_x) == MHI_CLIENT_BOOT_LOG_IN))
|
||||
|
||||
#define CHAN_EDL(_x) (((_x) == MHI_CLIENT_EDL_OUT) || \
|
||||
((_x) == MHI_CLIENT_EDL_IN))
|
||||
|
||||
#define RESERVED_CHAN(_x) (((_x) == MHI_CLIENT_RESERVED_0) || \
|
||||
((_x) >= MHI_CLIENT_RESERVED_1_LOWER && (_x) <= MHI_CLIENT_RESERVED_1_UPPER) || \
|
||||
((_x) >= MHI_CLIENT_RESERVED_2_LOWER && (_x) <= MHI_CLIENT_RESERVED_2_UPPER) || \
|
||||
((_x) >= MHI_CLIENT_RESERVED_3_LOWER && (_x) <= MHI_CLIENT_RESERVED_3_UPPER) || \
|
||||
((_x) >= MHI_CLIENT_RESERVED_4_LOWER && (_x) <= MHI_CLIENT_RESERVED_4_UPPER) || \
|
||||
((_x) >= MHI_CLIENT_RESERVED_5_LOWER))
|
||||
|
||||
#define VALID_CHAN(_x) ((((_x) >= 0) && ((_x) < MHI_MAX_CHANNELS)))
|
||||
|
||||
#define MHI_HW_CHAN(_x) ((_x) == MHI_CLIENT_IP_HW_0_OUT || \
|
||||
(_x) == MHI_CLIENT_IP_HW_0_IN || \
|
||||
(_x) == MHI_CLIENT_ADPL)
|
||||
|
||||
#define MIN(_x,_y) ((_x) < (_y) ? (_x): (_y))
|
||||
|
||||
struct mhi_chan;
|
||||
struct mhi_event;
|
||||
struct mhi_ctxt;
|
||||
struct mhi_cmd;
|
||||
struct image_info;
|
||||
struct bhi_vec_entry;
|
||||
struct mhi_cntrl_data;
|
||||
|
||||
/**
|
||||
* enum MHI_CB - MHI callback
|
||||
* @MHI_CB_IDLE: MHI entered idle state
|
||||
* @MHI_CB_PENDING_DATA: New data available for client to process
|
||||
* @MHI_CB_LPM_ENTER: MHI host entered low power mode
|
||||
* @MHI_CB_LPM_EXIT: MHI host about to exit low power mode
|
||||
* @MHI_CB_EE_RDDM: MHI device entered RDDM execution enviornment
|
||||
*/
|
||||
enum MHI_CB {
|
||||
MHI_CB_IDLE,
|
||||
MHI_CB_PENDING_DATA,
|
||||
MHI_CB_LPM_ENTER,
|
||||
MHI_CB_LPM_EXIT,
|
||||
MHI_CB_EE_RDDM,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum MHI_DEBUG_LEVL - various debugging level
|
||||
*/
|
||||
enum MHI_DEBUG_LEVEL {
|
||||
MHI_MSG_LVL_VERBOSE,
|
||||
MHI_MSG_LVL_INFO,
|
||||
MHI_MSG_LVL_ERROR,
|
||||
MHI_MSG_LVL_CRITICAL,
|
||||
MHI_MSG_LVL_MASK_ALL,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum MHI_FLAGS - Transfer flags
|
||||
* @MHI_EOB: End of buffer for bulk transfer
|
||||
* @MHI_EOT: End of transfer
|
||||
* @MHI_CHAIN: Linked transfer
|
||||
*/
|
||||
enum MHI_FLAGS {
|
||||
MHI_EOB,
|
||||
MHI_EOT,
|
||||
MHI_CHAIN,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct image_info - firmware and rddm table table
|
||||
* @mhi_buf - Contain device firmware and rddm table
|
||||
* @entries - # of entries in table
|
||||
*/
|
||||
struct image_info {
|
||||
struct mhi_buf *mhi_buf;
|
||||
struct bhi_vec_entry *bhi_vec;
|
||||
u32 entries;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mhi_controller - Master controller structure for external modem
|
||||
* @dev: Device associated with this controller
|
||||
* @of_node: DT that has MHI configuration information
|
||||
* @regs: Points to base of MHI MMIO register space
|
||||
* @bhi: Points to base of MHI BHI register space
|
||||
* @wake_db: MHI WAKE doorbell register address
|
||||
* @dev_id: PCIe device id of the external device
|
||||
* @domain: PCIe domain the device connected to
|
||||
* @bus: PCIe bus the device assigned to
|
||||
* @slot: PCIe slot for the modem
|
||||
* @iova_start: IOMMU starting address for data
|
||||
* @iova_stop: IOMMU stop address for data
|
||||
* @fw_image: Firmware image name for normal booting
|
||||
* @edl_image: Firmware image name for emergency download mode
|
||||
* @fbc_download: MHI host needs to do complete image transfer
|
||||
* @rddm_size: RAM dump size that host should allocate for debugging purpose
|
||||
* @sbl_size: SBL image size
|
||||
* @seg_len: BHIe vector size
|
||||
* @fbc_image: Points to firmware image buffer
|
||||
* @rddm_image: Points to RAM dump buffer
|
||||
* @max_chan: Maximum number of channels controller support
|
||||
* @mhi_chan: Points to channel configuration table
|
||||
* @lpm_chans: List of channels that require LPM notifications
|
||||
* @total_ev_rings: Total # of event rings allocated
|
||||
* @hw_ev_rings: Number of hardware event rings
|
||||
* @sw_ev_rings: Number of software event rings
|
||||
* @msi_required: Number of msi required to operate
|
||||
* @msi_allocated: Number of msi allocated by bus master
|
||||
* @irq: base irq # to request
|
||||
* @mhi_event: MHI event ring configurations table
|
||||
* @mhi_cmd: MHI command ring configurations table
|
||||
* @mhi_ctxt: MHI device context, shared memory between host and device
|
||||
* @timeout_ms: Timeout in ms for state transitions
|
||||
* @pm_state: Power management state
|
||||
* @ee: MHI device execution environment
|
||||
* @dev_state: MHI STATE
|
||||
* @status_cb: CB function to notify various power states to but master
|
||||
* @link_status: Query link status in case of abnormal value read from device
|
||||
* @runtime_get: Async runtime resume function
|
||||
* @runtimet_put: Release votes
|
||||
* @priv_data: Points to bus master's private data
|
||||
*/
|
||||
struct mhi_controller {
|
||||
struct list_head node;
|
||||
|
||||
/* device node for iommu ops */
|
||||
struct device *dev;
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
/* mmio base */
|
||||
void __iomem *regs;
|
||||
void __iomem *bhi;
|
||||
void __iomem *wake_db;
|
||||
|
||||
/* device topology */
|
||||
u32 dev_id;
|
||||
u32 domain;
|
||||
u32 bus;
|
||||
u32 slot;
|
||||
|
||||
/* addressing window */
|
||||
dma_addr_t iova_start;
|
||||
dma_addr_t iova_stop;
|
||||
|
||||
/* fw images */
|
||||
const char *fw_image;
|
||||
const char *edl_image;
|
||||
|
||||
/* mhi host manages downloading entire fbc images */
|
||||
bool fbc_download;
|
||||
size_t rddm_size;
|
||||
size_t sbl_size;
|
||||
size_t seg_len;
|
||||
u32 session_id;
|
||||
u32 sequence_id;
|
||||
struct image_info *fbc_image;
|
||||
struct image_info *rddm_image;
|
||||
|
||||
/* physical channel config data */
|
||||
u32 max_chan;
|
||||
struct mhi_chan *mhi_chan;
|
||||
struct list_head lpm_chans; /* these chan require lpm notification */
|
||||
|
||||
/* physical event config data */
|
||||
u32 total_ev_rings;
|
||||
u32 hw_ev_rings;
|
||||
u32 sw_ev_rings;
|
||||
u32 msi_required;
|
||||
u32 msi_allocated;
|
||||
int irq[8]; /* interrupt table */
|
||||
struct mhi_event *mhi_event;
|
||||
|
||||
/* cmd rings */
|
||||
struct mhi_cmd *mhi_cmd;
|
||||
|
||||
/* mhi context (shared with device) */
|
||||
struct mhi_ctxt *mhi_ctxt;
|
||||
|
||||
u32 timeout_ms;
|
||||
|
||||
/* caller should grab pm_mutex for suspend/resume operations */
|
||||
struct mutex pm_mutex;
|
||||
bool pre_init;
|
||||
rwlock_t pm_lock;
|
||||
u32 pm_state;
|
||||
u32 ee;
|
||||
u32 dev_state;
|
||||
bool wake_set;
|
||||
atomic_t dev_wake;
|
||||
atomic_t alloc_size;
|
||||
struct list_head transition_list;
|
||||
spinlock_t transition_lock;
|
||||
spinlock_t wlock;
|
||||
|
||||
/* debug counters */
|
||||
u32 M0, M1, M2, M3;
|
||||
|
||||
/* worker for different state transitions */
|
||||
struct work_struct st_worker;
|
||||
struct work_struct fw_worker;
|
||||
struct work_struct m1_worker;
|
||||
struct work_struct syserr_worker;
|
||||
wait_queue_head_t state_event;
|
||||
|
||||
/* shadow functions */
|
||||
void (*status_cb)(struct mhi_controller *mhi_cntrl, void *piv,
|
||||
enum MHI_CB reason);
|
||||
int (*link_status)(struct mhi_controller *mhi_cntrl, void *priv);
|
||||
void (*wake_get)(struct mhi_controller *mhi_cntrl, bool override);
|
||||
void (*wake_put)(struct mhi_controller *mhi_cntrl, bool override);
|
||||
int (*runtime_get)(struct mhi_controller *mhi_cntrl, void *priv);
|
||||
void (*runtime_put)(struct mhi_controller *mhi_cntrl, void *priv);
|
||||
|
||||
/* channel to control DTR messaging */
|
||||
struct mhi_device *dtr_dev;
|
||||
|
||||
/* kernel log level */
|
||||
enum MHI_DEBUG_LEVEL klog_lvl;
|
||||
|
||||
/* private log level controller driver to set */
|
||||
enum MHI_DEBUG_LEVEL log_lvl;
|
||||
|
||||
/* controller specific data */
|
||||
void *priv_data;
|
||||
void *log_buf;
|
||||
struct dentry *dentry;
|
||||
struct dentry *parent;
|
||||
struct mhi_cntrl_data *data;
|
||||
|
||||
struct miscdevice miscdev;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mhi_device - mhi device structure associated bind to channel
|
||||
* @dev: Device associated with the channels
|
||||
* @mtu: Maximum # of bytes controller support
|
||||
* @ul_chan_id: MHI channel id for UL transfer
|
||||
* @dl_chan_id: MHI channel id for DL transfer
|
||||
* @priv: Driver private data
|
||||
*/
|
||||
struct mhi_device {
|
||||
struct device dev;
|
||||
u32 dev_id;
|
||||
u32 domain;
|
||||
u32 bus;
|
||||
u32 slot;
|
||||
size_t mtu;
|
||||
int ul_chan_id;
|
||||
int dl_chan_id;
|
||||
int ul_event_id;
|
||||
int dl_event_id;
|
||||
const struct mhi_device_id *id;
|
||||
const char *chan_name;
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
struct mhi_chan *ul_chan;
|
||||
struct mhi_chan *dl_chan;
|
||||
atomic_t dev_wake;
|
||||
void *priv_data;
|
||||
int (*ul_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS flags);
|
||||
int (*dl_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS flags);
|
||||
void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB reason);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mhi_result - Completed buffer information
|
||||
* @buf_addr: Address of data buffer
|
||||
* @dir: Channel direction
|
||||
* @bytes_xfer: # of bytes transferred
|
||||
* @transaction_status: Status of last trasnferred
|
||||
*/
|
||||
struct mhi_result {
|
||||
void *buf_addr;
|
||||
enum dma_data_direction dir;
|
||||
size_t bytes_xferd;
|
||||
int transaction_status;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mhi_buf - Describes the buffer
|
||||
* @buf: cpu address for the buffer
|
||||
* @phys_addr: physical address of the buffer
|
||||
* @dma_addr: iommu address for the buffer
|
||||
* @len: # of bytes
|
||||
* @name: Buffer label, for offload channel configurations name must be:
|
||||
* ECA - Event context array data
|
||||
* CCA - Channel context array data
|
||||
*/
|
||||
struct mhi_buf {
|
||||
void *buf;
|
||||
phys_addr_t phys_addr;
|
||||
dma_addr_t dma_addr;
|
||||
size_t len;
|
||||
const char *name; /* ECA, CCA */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mhi_driver - mhi driver information
|
||||
* @id_table: NULL terminated channel ID names
|
||||
* @ul_xfer_cb: UL data transfer callback
|
||||
* @dl_xfer_cb: DL data transfer callback
|
||||
* @status_cb: Asynchronous status callback
|
||||
*/
|
||||
struct mhi_driver {
|
||||
const struct mhi_device_id *id_table;
|
||||
int (*probe)(struct mhi_device *mhi_dev,
|
||||
const struct mhi_device_id *id);
|
||||
void (*remove)(struct mhi_device *mhi_dev);
|
||||
void (*ul_xfer_cb)(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *result);
|
||||
void (*dl_xfer_cb)(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *result);
|
||||
void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb);
|
||||
struct device_driver driver;
|
||||
};
|
||||
|
||||
#define to_mhi_driver(drv) container_of(drv, struct mhi_driver, driver)
|
||||
#define to_mhi_device(dev) container_of(dev, struct mhi_device, dev)
|
||||
|
||||
static inline void mhi_device_set_devdata(struct mhi_device *mhi_dev,
|
||||
void *priv)
|
||||
{
|
||||
mhi_dev->priv_data = priv;
|
||||
}
|
||||
|
||||
static inline void *mhi_device_get_devdata(struct mhi_device *mhi_dev)
|
||||
{
|
||||
return mhi_dev->priv_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* mhi_queue_transfer - Queue a buffer to hardware
|
||||
* All transfers are asyncronous transfers
|
||||
* @mhi_dev: Device associated with the channels
|
||||
* @dir: Data direction
|
||||
* @buf: Data buffer (skb for hardware channels)
|
||||
* @len: Size in bytes
|
||||
* @mflags: Interrupt flags for the device
|
||||
*/
|
||||
static inline int mhi_queue_transfer(struct mhi_device *mhi_dev,
|
||||
enum dma_data_direction dir,
|
||||
void *buf,
|
||||
size_t len,
|
||||
enum MHI_FLAGS mflags)
|
||||
{
|
||||
if (dir == DMA_TO_DEVICE)
|
||||
return mhi_dev->ul_xfer(mhi_dev, mhi_dev->ul_chan, buf, len,
|
||||
mflags);
|
||||
else
|
||||
return mhi_dev->dl_xfer(mhi_dev, mhi_dev->dl_chan, buf, len,
|
||||
mflags);
|
||||
}
|
||||
|
||||
static inline void *mhi_controller_get_devdata(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
return mhi_cntrl->priv_data;
|
||||
}
|
||||
|
||||
static inline void mhi_free_controller(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
kfree(mhi_cntrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* mhi_driver_register - Register driver with MHI framework
|
||||
* @mhi_drv: mhi_driver structure
|
||||
*/
|
||||
int mhi_driver_register(struct mhi_driver *mhi_drv);
|
||||
|
||||
/**
|
||||
* mhi_driver_unregister - Unregister a driver for mhi_devices
|
||||
* @mhi_drv: mhi_driver structure
|
||||
*/
|
||||
void mhi_driver_unregister(struct mhi_driver *mhi_drv);
|
||||
|
||||
/**
|
||||
* mhi_device_configure - configure ECA or CCA context
|
||||
* For offload channels that client manage, call this
|
||||
* function to configure channel context or event context
|
||||
* array associated with the channel
|
||||
* @mhi_div: Device associated with the channels
|
||||
* @dir: Direction of the channel
|
||||
* @mhi_buf: Configuration data
|
||||
* @elements: # of configuration elements
|
||||
*/
|
||||
int mhi_device_configure(struct mhi_device *mhi_div,
|
||||
enum dma_data_direction dir,
|
||||
struct mhi_buf *mhi_buf,
|
||||
int elements);
|
||||
|
||||
/**
|
||||
* mhi_device_get - disable all low power modes
|
||||
* Only disables lpm, does not immediately exit low power mode
|
||||
* if controller already in a low power mode
|
||||
* @mhi_dev: Device associated with the channels
|
||||
*/
|
||||
void mhi_device_get(struct mhi_device *mhi_dev);
|
||||
|
||||
/**
|
||||
* mhi_device_get_sync - disable all low power modes
|
||||
* Synchronously disable all low power, exit low power mode if
|
||||
* controller already in a low power state
|
||||
* @mhi_dev: Device associated with the channels
|
||||
*/
|
||||
int mhi_device_get_sync(struct mhi_device *mhi_dev);
|
||||
|
||||
/**
|
||||
* mhi_device_put - re-enable low power modes
|
||||
* @mhi_dev: Device associated with the channels
|
||||
*/
|
||||
void mhi_device_put(struct mhi_device *mhi_dev);
|
||||
|
||||
/**
|
||||
* mhi_prepare_for_transfer - setup channel for data transfer
|
||||
* Moves both UL and DL channel from RESET to START state
|
||||
* @mhi_dev: Device associated with the channels
|
||||
*/
|
||||
int mhi_prepare_for_transfer(struct mhi_device *mhi_dev);
|
||||
|
||||
/**
|
||||
* mhi_unprepare_from_transfer -unprepare the channels
|
||||
* Moves both UL and DL channels to RESET state
|
||||
* @mhi_dev: Device associated with the channels
|
||||
*/
|
||||
void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev);
|
||||
|
||||
/**
|
||||
* mhi_get_no_free_descriptors - Get transfer ring length
|
||||
* Get # of TD available to queue buffers
|
||||
* @mhi_dev: Device associated with the channels
|
||||
* @dir: Direction of the channel
|
||||
*/
|
||||
int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev,
|
||||
enum dma_data_direction dir);
|
||||
|
||||
/**
|
||||
* mhi_poll - poll for any available data to consume
|
||||
* This is only applicable for DL direction
|
||||
* @mhi_dev: Device associated with the channels
|
||||
* @budget: In descriptors to service before returning
|
||||
*/
|
||||
int mhi_poll(struct mhi_device *mhi_dev, u32 budget);
|
||||
|
||||
/**
|
||||
* mhi_ioctl - user space IOCTL support for MHI channels
|
||||
* Native support for setting TIOCM
|
||||
* @mhi_dev: Device associated with the channels
|
||||
* @cmd: IOCTL cmd
|
||||
* @arg: Optional parameter, iotcl cmd specific
|
||||
*/
|
||||
long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg);
|
||||
|
||||
/**
|
||||
* mhi_alloc_controller - Allocate mhi_controller structure
|
||||
* Allocate controller structure and additional data for controller
|
||||
* private data. You may get the private data pointer by calling
|
||||
* mhi_controller_get_devdata
|
||||
* @size: # of additional bytes to allocate
|
||||
*/
|
||||
struct mhi_controller *mhi_alloc_controller(size_t size);
|
||||
|
||||
/**
|
||||
* mhi_register_mhi_controller - Register MHI controller
|
||||
* Registers MHI controller with MHI bus framework. DT must be supported
|
||||
* @mhi_cntrl: MHI controller to register
|
||||
*/
|
||||
int mhi_register_mhi_controller(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_bdf_to_controller - Look up a registered controller
|
||||
* Search for controller based on device identification
|
||||
* @domain: RC domain of the device
|
||||
* @bus: Bus device connected to
|
||||
* @slot: Slot device assigned to
|
||||
* @dev_id: Device Identification
|
||||
*/
|
||||
struct mhi_controller *mhi_bdf_to_controller(u32 domain, u32 bus, u32 slot,
|
||||
u32 dev_id);
|
||||
|
||||
/**
|
||||
* mhi_prepare_for_power_up - Do pre-initialization before power up
|
||||
* This is optional, call this before power up if controller do not
|
||||
* want bus framework to automatically free any allocated memory during shutdown
|
||||
* process.
|
||||
* @mhi_cntrl: MHI controller
|
||||
*/
|
||||
int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_async_power_up - Starts MHI power up sequence
|
||||
* @mhi_cntrl: MHI controller
|
||||
*/
|
||||
int mhi_async_power_up(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_sync_power_up(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_power_down - Start MHI power down sequence
|
||||
* @mhi_cntrl: MHI controller
|
||||
* @graceful: link is still accessible, do a graceful shutdown process otherwise
|
||||
* we will shutdown host w/o putting device into RESET state
|
||||
*/
|
||||
void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful);
|
||||
|
||||
/**
|
||||
* mhi_unprepare_after_powre_down - free any allocated memory for power up
|
||||
* @mhi_cntrl: MHI controller
|
||||
*/
|
||||
void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_pm_suspend - Move MHI into a suspended state
|
||||
* Transition to MHI state M3 state from M0||M1||M2 state
|
||||
* @mhi_cntrl: MHI controller
|
||||
*/
|
||||
int mhi_pm_suspend(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_pm_resume - Resume MHI from suspended state
|
||||
* Transition to MHI state M0 state from M3 state
|
||||
* @mhi_cntrl: MHI controller
|
||||
*/
|
||||
int mhi_pm_resume(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_download_rddm_img - Download ramdump image from device for
|
||||
* debugging purpose.
|
||||
* @mhi_cntrl: MHI controller
|
||||
* @in_panic: If we trying to capture image while in kernel panic
|
||||
*/
|
||||
int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic);
|
||||
|
||||
/**
|
||||
* mhi_force_rddm_mode - Force external device into rddm mode
|
||||
* to collect device ramdump. This is useful if host driver assert
|
||||
* and we need to see device state as well.
|
||||
* @mhi_cntrl: MHI controller
|
||||
*/
|
||||
int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
int mhi_cntrl_register_miscdev(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_cntrl_deregister_miscdev(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
extern int mhi_debug_mask;
|
||||
|
||||
#define MHI_VERB(fmt, ...) do { \
|
||||
if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_VERBOSE) \
|
||||
pr_err("VERBOSE:[D][%s] " fmt, __func__, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define MHI_LOG(fmt, ...) do { \
|
||||
if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_INFO) \
|
||||
pr_err("INFO:[I][%s] " fmt, __func__, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
#define MHI_ERR(fmt, ...) do { \
|
||||
if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_ERROR) \
|
||||
pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define MHI_CRITICAL(fmt, ...) do { \
|
||||
if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_CRITICAL) \
|
||||
pr_err("ALERT:[C][%s] " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#ifndef MHI_NAME_SIZE
|
||||
#define MHI_NAME_SIZE 32
|
||||
/**
|
||||
* * struct mhi_device_id - MHI device identification
|
||||
* * @chan: MHI channel name
|
||||
* * @driver_data: driver data;
|
||||
* */
|
||||
struct mhi_device_id {
|
||||
const char chan[MHI_NAME_SIZE];
|
||||
unsigned long driver_data;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _MHI_H_ */
|
||||
@@ -1,878 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include "mhi.h"
|
||||
#include "mhi_internal.h"
|
||||
|
||||
#define IOCTL_BHI_GETDEVINFO 0x8BE0 + 1
|
||||
#define IOCTL_BHI_WRITEIMAGE 0x8BE0 + 2
|
||||
|
||||
/* Software defines */
|
||||
/* BHI Version */
|
||||
#define BHI_MAJOR_VERSION 0x1
|
||||
#define BHI_MINOR_VERSION 0x1
|
||||
|
||||
#define MSMHWID_NUMDWORDS 6 /* Number of dwords that make the MSMHWID */
|
||||
#define OEMPKHASH_NUMDWORDS 48 /* Number of dwords that make the OEM PK HASH */
|
||||
|
||||
#define IsPBLExecEnv(ExecEnv) ((ExecEnv == MHI_EE_PBL) || (ExecEnv == MHI_EE_EDL) )
|
||||
|
||||
typedef u32 ULONG;
|
||||
|
||||
typedef struct _bhi_info_type
|
||||
{
|
||||
ULONG bhi_ver_minor;
|
||||
ULONG bhi_ver_major;
|
||||
ULONG bhi_image_address_low;
|
||||
ULONG bhi_image_address_high;
|
||||
ULONG bhi_image_size;
|
||||
ULONG bhi_rsvd1;
|
||||
ULONG bhi_imgtxdb;
|
||||
ULONG bhi_rsvd2;
|
||||
ULONG bhi_msivec;
|
||||
ULONG bhi_rsvd3;
|
||||
ULONG bhi_ee;
|
||||
ULONG bhi_status;
|
||||
ULONG bhi_errorcode;
|
||||
ULONG bhi_errdbg1;
|
||||
ULONG bhi_errdbg2;
|
||||
ULONG bhi_errdbg3;
|
||||
ULONG bhi_sernum;
|
||||
ULONG bhi_sblantirollbackver;
|
||||
ULONG bhi_numsegs;
|
||||
ULONG bhi_msmhwid[6];
|
||||
ULONG bhi_oempkhash[48];
|
||||
ULONG bhi_rsvd5;
|
||||
}BHI_INFO_TYPE, *PBHI_INFO_TYPE;
|
||||
|
||||
#if 0
|
||||
static void PrintBhiInfo(BHI_INFO_TYPE *bhi_info)
|
||||
{
|
||||
ULONG index;
|
||||
|
||||
printk("BHI Device Info...\n");
|
||||
printk("BHI Version = { Major = 0x%X Minor = 0x%X}\n", bhi_info->bhi_ver_major, bhi_info->bhi_ver_minor);
|
||||
printk("BHI Execution Environment = 0x%X\n", bhi_info->bhi_ee);
|
||||
printk("BHI Status = 0x%X\n", bhi_info->bhi_status);
|
||||
printk("BHI Error code = 0x%X { Dbg1 = 0x%X Dbg2 = 0x%X Dbg3 = 0x%X }\n", bhi_info->bhi_errorcode, bhi_info->bhi_errdbg1, bhi_info->bhi_errdbg2, bhi_info->bhi_errdbg3);
|
||||
printk("BHI Serial Number = 0x%X\n", bhi_info->bhi_sernum);
|
||||
printk("BHI SBL Anti-Rollback Ver = 0x%X\n", bhi_info->bhi_sblantirollbackver);
|
||||
printk("BHI Number of Segments = 0x%X\n", bhi_info->bhi_numsegs);
|
||||
printk("BHI MSM HW-Id = ");
|
||||
for (index = 0; index < 6; index++)
|
||||
{
|
||||
printk("0x%X ", bhi_info->bhi_msmhwid[index]);
|
||||
}
|
||||
printk("\n");
|
||||
|
||||
printk("BHI OEM PK Hash = \n");
|
||||
for (index = 0; index < 24; index++)
|
||||
{
|
||||
printk("0x%X ", bhi_info->bhi_oempkhash[index]);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static u32 bhi_read_reg(struct mhi_controller *mhi_cntrl, u32 offset)
|
||||
{
|
||||
u32 out = 0;
|
||||
int ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, offset, &out);
|
||||
|
||||
return (ret) ? 0 : out;
|
||||
}
|
||||
|
||||
static int BhiRead(struct mhi_controller *mhi_cntrl, BHI_INFO_TYPE *bhi_info)
|
||||
{
|
||||
ULONG index;
|
||||
|
||||
memset(bhi_info, 0x00, sizeof(BHI_INFO_TYPE));
|
||||
|
||||
/* bhi_ver */
|
||||
bhi_info->bhi_ver_minor = bhi_read_reg(mhi_cntrl, BHI_BHIVERSION_MINOR);
|
||||
bhi_info->bhi_ver_major = bhi_read_reg(mhi_cntrl, BHI_BHIVERSION_MINOR);
|
||||
bhi_info->bhi_image_address_low = bhi_read_reg(mhi_cntrl, BHI_IMGADDR_LOW);
|
||||
bhi_info->bhi_image_address_high = bhi_read_reg(mhi_cntrl, BHI_IMGADDR_HIGH);
|
||||
bhi_info->bhi_image_size = bhi_read_reg(mhi_cntrl, BHI_IMGSIZE);
|
||||
bhi_info->bhi_rsvd1 = bhi_read_reg(mhi_cntrl, BHI_RSVD1);
|
||||
bhi_info->bhi_imgtxdb = bhi_read_reg(mhi_cntrl, BHI_IMGTXDB);
|
||||
bhi_info->bhi_rsvd2 = bhi_read_reg(mhi_cntrl, BHI_RSVD2);
|
||||
bhi_info->bhi_msivec = bhi_read_reg(mhi_cntrl, BHI_INTVEC);
|
||||
bhi_info->bhi_rsvd3 = bhi_read_reg(mhi_cntrl, BHI_RSVD3);
|
||||
bhi_info->bhi_ee = bhi_read_reg(mhi_cntrl, BHI_EXECENV);
|
||||
bhi_info->bhi_status = bhi_read_reg(mhi_cntrl, BHI_STATUS);
|
||||
bhi_info->bhi_errorcode = bhi_read_reg(mhi_cntrl, BHI_ERRCODE);
|
||||
bhi_info->bhi_errdbg1 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG1);
|
||||
bhi_info->bhi_errdbg2 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG2);
|
||||
bhi_info->bhi_errdbg3 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG3);
|
||||
bhi_info->bhi_sernum = bhi_read_reg(mhi_cntrl, BHI_SERIALNUM);
|
||||
bhi_info->bhi_sblantirollbackver = bhi_read_reg(mhi_cntrl, BHI_SBLANTIROLLVER);
|
||||
bhi_info->bhi_numsegs = bhi_read_reg(mhi_cntrl, BHI_NUMSEG);
|
||||
for (index = 0; index < MSMHWID_NUMDWORDS; index++)
|
||||
{
|
||||
bhi_info->bhi_msmhwid[index] = bhi_read_reg(mhi_cntrl, BHI_MSMHWID(index));
|
||||
}
|
||||
for (index = 0; index < OEMPKHASH_NUMDWORDS; index++)
|
||||
{
|
||||
bhi_info->bhi_oempkhash[index] = bhi_read_reg(mhi_cntrl, BHI_OEMPKHASH(index));
|
||||
}
|
||||
bhi_info->bhi_rsvd5 = bhi_read_reg(mhi_cntrl, BHI_RSVD5);
|
||||
//PrintBhiInfo(bhi_info);
|
||||
/* Check the Execution Environment */
|
||||
if (!IsPBLExecEnv(bhi_info->bhi_ee))
|
||||
{
|
||||
printk("E - EE: 0x%X Expected PBL/EDL\n", bhi_info->bhi_ee);
|
||||
}
|
||||
|
||||
/* Return the number of bytes read */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* setup rddm vector table for rddm transfer */
|
||||
static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *img_info)
|
||||
{
|
||||
struct mhi_buf *mhi_buf = img_info->mhi_buf;
|
||||
struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) {
|
||||
MHI_VERB("Setting vector:%pad size:%zu\n",
|
||||
&mhi_buf->dma_addr, mhi_buf->len);
|
||||
bhi_vec->dma_addr = mhi_buf->dma_addr;
|
||||
bhi_vec->size = mhi_buf->len;
|
||||
}
|
||||
}
|
||||
|
||||
/* collect rddm during kernel panic */
|
||||
static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
int ret;
|
||||
struct mhi_buf *mhi_buf;
|
||||
u32 sequence_id;
|
||||
u32 rx_status;
|
||||
enum MHI_EE ee;
|
||||
struct image_info *rddm_image = mhi_cntrl->rddm_image;
|
||||
const u32 delayus = 100;
|
||||
u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus;
|
||||
void __iomem *base = mhi_cntrl->bhi;
|
||||
|
||||
MHI_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state),
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
/*
|
||||
* This should only be executing during a kernel panic, we expect all
|
||||
* other cores to shutdown while we're collecting rddm buffer. After
|
||||
* returning from this function, we expect device to reset.
|
||||
*
|
||||
* Normaly, we would read/write pm_state only after grabbing
|
||||
* pm_lock, since we're in a panic, skipping it.
|
||||
*/
|
||||
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
* There is no gurantee this state change would take effect since
|
||||
* we're setting it w/o grabbing pmlock, it's best effort
|
||||
*/
|
||||
mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT;
|
||||
/* update should take the effect immediately */
|
||||
smp_wmb();
|
||||
|
||||
/* setup the RX vector table */
|
||||
mhi_rddm_prepare(mhi_cntrl, rddm_image);
|
||||
mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1];
|
||||
|
||||
MHI_LOG("Starting BHIe programming for RDDM\n");
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS,
|
||||
upper_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS,
|
||||
lower_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
|
||||
sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
|
||||
|
||||
if (unlikely(!sequence_id))
|
||||
sequence_id = 1;
|
||||
|
||||
|
||||
mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
|
||||
BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT,
|
||||
sequence_id);
|
||||
|
||||
MHI_LOG("Trigger device into RDDM mode\n");
|
||||
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR);
|
||||
|
||||
MHI_LOG("Waiting for image download completion\n");
|
||||
while (retry--) {
|
||||
ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS,
|
||||
BHIE_RXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_RXVECSTATUS_STATUS_SHFT,
|
||||
&rx_status);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) {
|
||||
MHI_LOG("RDDM successfully collected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
udelay(delayus);
|
||||
}
|
||||
|
||||
ee = mhi_get_exec_env(mhi_cntrl);
|
||||
ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status);
|
||||
|
||||
MHI_ERR("Did not complete RDDM transfer\n");
|
||||
MHI_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee));
|
||||
MHI_ERR("RXVEC_STATUS:0x%x, ret:%d\n", rx_status, ret);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* download ramdump image from device */
|
||||
int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic)
|
||||
{
|
||||
void __iomem *base = mhi_cntrl->bhi;
|
||||
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
|
||||
struct image_info *rddm_image = mhi_cntrl->rddm_image;
|
||||
struct mhi_buf *mhi_buf;
|
||||
int ret;
|
||||
u32 rx_status;
|
||||
u32 sequence_id;
|
||||
|
||||
if (!rddm_image)
|
||||
return -ENOMEM;
|
||||
|
||||
if (in_panic)
|
||||
return __mhi_download_rddm_in_panic(mhi_cntrl);
|
||||
|
||||
MHI_LOG("Waiting for device to enter RDDM state from EE:%s\n",
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_cntrl->ee == MHI_EE_RDDM ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
MHI_ERR("MHI is not in valid state, pm_state:%s ee:%s\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image);
|
||||
|
||||
/* vector table is the last entry */
|
||||
mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1];
|
||||
|
||||
read_lock_bh(pm_lock);
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
read_unlock_bh(pm_lock);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
MHI_LOG("Starting BHIe Programming for RDDM\n");
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS,
|
||||
upper_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS,
|
||||
lower_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
|
||||
|
||||
sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
|
||||
mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
|
||||
BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT,
|
||||
sequence_id);
|
||||
read_unlock_bh(pm_lock);
|
||||
|
||||
MHI_LOG("Upper:0x%x Lower:0x%x len:0x%zx sequence:%u\n",
|
||||
upper_32_bits(mhi_buf->dma_addr),
|
||||
lower_32_bits(mhi_buf->dma_addr),
|
||||
mhi_buf->len, sequence_id);
|
||||
MHI_LOG("Waiting for image download completion\n");
|
||||
|
||||
/* waiting for image download completion */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
|
||||
mhi_read_reg_field(mhi_cntrl, base,
|
||||
BHIE_RXVECSTATUS_OFFS,
|
||||
BHIE_RXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_RXVECSTATUS_STATUS_SHFT,
|
||||
&rx_status) || rx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
return -EIO;
|
||||
|
||||
return (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_download_rddm_img);
|
||||
|
||||
static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl,
|
||||
const struct mhi_buf *mhi_buf)
|
||||
{
|
||||
void __iomem *base = mhi_cntrl->bhi;
|
||||
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
|
||||
u32 tx_status;
|
||||
|
||||
read_lock_bh(pm_lock);
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
read_unlock_bh(pm_lock);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
MHI_LOG("Starting BHIe Programming\n");
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_HIGH_OFFS,
|
||||
upper_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_LOW_OFFS,
|
||||
lower_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECSIZE_OFFS, mhi_buf->len);
|
||||
|
||||
mhi_cntrl->sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK;
|
||||
mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS,
|
||||
BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT,
|
||||
mhi_cntrl->sequence_id);
|
||||
read_unlock_bh(pm_lock);
|
||||
|
||||
MHI_LOG("Upper:0x%x Lower:0x%x len:0x%zx sequence:%u\n",
|
||||
upper_32_bits(mhi_buf->dma_addr),
|
||||
lower_32_bits(mhi_buf->dma_addr),
|
||||
mhi_buf->len, mhi_cntrl->sequence_id);
|
||||
MHI_LOG("Waiting for image transfer completion\n");
|
||||
|
||||
/* waiting for image download completion */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
|
||||
mhi_read_reg_field(mhi_cntrl, base,
|
||||
BHIE_TXVECSTATUS_OFFS,
|
||||
BHIE_TXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_TXVECSTATUS_STATUS_SHFT,
|
||||
&tx_status) || tx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
return -EIO;
|
||||
|
||||
return (tx_status == BHIE_TXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl,
|
||||
void *buf,
|
||||
size_t size)
|
||||
{
|
||||
u32 tx_status, val;
|
||||
int i, ret;
|
||||
void __iomem *base = mhi_cntrl->bhi;
|
||||
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
|
||||
dma_addr_t phys = dma_map_single(mhi_cntrl->dev, buf, size,
|
||||
DMA_TO_DEVICE);
|
||||
struct {
|
||||
char *name;
|
||||
u32 offset;
|
||||
} error_reg[] = {
|
||||
{ "ERROR_CODE", BHI_ERRCODE },
|
||||
{ "ERROR_DBG1", BHI_ERRDBG1 },
|
||||
{ "ERROR_DBG2", BHI_ERRDBG2 },
|
||||
{ "ERROR_DBG3", BHI_ERRDBG3 },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
if (dma_mapping_error(mhi_cntrl->dev, phys))
|
||||
return -ENOMEM;
|
||||
|
||||
MHI_LOG("Starting BHI programming\n");
|
||||
|
||||
/* program start sbl download via bhi protocol */
|
||||
read_lock_bh(pm_lock);
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
read_unlock_bh(pm_lock);
|
||||
goto invalid_pm_state;
|
||||
}
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0);
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, upper_32_bits(phys));
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, lower_32_bits(phys));
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size);
|
||||
mhi_cntrl->session_id = prandom_u32() & BHI_TXDB_SEQNUM_BMSK;
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, mhi_cntrl->session_id);
|
||||
read_unlock_bh(pm_lock);
|
||||
|
||||
MHI_LOG("Waiting for image transfer completion\n");
|
||||
|
||||
/* waiting for image download completion */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
/*MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||*/
|
||||
mhi_read_reg_field(mhi_cntrl, base, BHI_STATUS,
|
||||
BHI_STATUS_MASK, BHI_STATUS_SHIFT,
|
||||
&tx_status) || tx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
#if 0
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
goto invalid_pm_state;
|
||||
#endif
|
||||
|
||||
MHI_LOG("image transfer status:%d\n", tx_status);
|
||||
|
||||
if (tx_status == BHI_STATUS_ERROR) {
|
||||
MHI_ERR("Image transfer failed\n");
|
||||
read_lock_bh(pm_lock);
|
||||
if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
for (i = 0; error_reg[i].name; i++) {
|
||||
ret = mhi_read_reg(mhi_cntrl, base,
|
||||
error_reg[i].offset, &val);
|
||||
if (ret)
|
||||
break;
|
||||
MHI_ERR("reg:%s value:0x%x\n",
|
||||
error_reg[i].name, val);
|
||||
}
|
||||
}
|
||||
read_unlock_bh(pm_lock);
|
||||
goto invalid_pm_state;
|
||||
}
|
||||
|
||||
dma_unmap_single(mhi_cntrl->dev, phys, size, DMA_TO_DEVICE);
|
||||
|
||||
return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT;
|
||||
|
||||
invalid_pm_state:
|
||||
dma_unmap_single(mhi_cntrl->dev, phys, size, DMA_TO_DEVICE);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *image_info)
|
||||
{
|
||||
int i;
|
||||
struct mhi_buf *mhi_buf = image_info->mhi_buf;
|
||||
|
||||
for (i = 0; i < image_info->entries; i++, mhi_buf++)
|
||||
mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf,
|
||||
mhi_buf->dma_addr);
|
||||
|
||||
kfree(image_info->mhi_buf);
|
||||
kfree(image_info);
|
||||
}
|
||||
|
||||
int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info **image_info,
|
||||
size_t alloc_size)
|
||||
{
|
||||
size_t seg_size = mhi_cntrl->seg_len;
|
||||
/* requier additional entry for vec table */
|
||||
int segments = DIV_ROUND_UP(alloc_size, seg_size) + 1;
|
||||
int i;
|
||||
struct image_info *img_info;
|
||||
struct mhi_buf *mhi_buf;
|
||||
|
||||
MHI_LOG("Allocating bytes:%zu seg_size:%zu total_seg:%u\n",
|
||||
alloc_size, seg_size, segments);
|
||||
|
||||
img_info = kzalloc(sizeof(*img_info), GFP_KERNEL);
|
||||
if (!img_info)
|
||||
return -ENOMEM;
|
||||
|
||||
/* allocate memory for entries */
|
||||
img_info->mhi_buf = kcalloc(segments, sizeof(*img_info->mhi_buf),
|
||||
GFP_KERNEL);
|
||||
if (!img_info->mhi_buf)
|
||||
goto error_alloc_mhi_buf;
|
||||
|
||||
/* allocate and populate vector table */
|
||||
mhi_buf = img_info->mhi_buf;
|
||||
for (i = 0; i < segments; i++, mhi_buf++) {
|
||||
size_t vec_size = seg_size;
|
||||
|
||||
/* last entry is for vector table */
|
||||
if (i == segments - 1)
|
||||
vec_size = sizeof(struct __packed bhi_vec_entry) * i;
|
||||
|
||||
mhi_buf->len = vec_size;
|
||||
mhi_buf->buf = mhi_alloc_coherent(mhi_cntrl, vec_size,
|
||||
&mhi_buf->dma_addr, GFP_KERNEL);
|
||||
if (!mhi_buf->buf)
|
||||
goto error_alloc_segment;
|
||||
|
||||
MHI_LOG("Entry:%d Address:0x%llx size:%zd\n", i,
|
||||
(u64)mhi_buf->dma_addr, mhi_buf->len);
|
||||
}
|
||||
|
||||
img_info->bhi_vec = img_info->mhi_buf[segments - 1].buf;
|
||||
img_info->entries = segments;
|
||||
*image_info = img_info;
|
||||
|
||||
MHI_LOG("Successfully allocated bhi vec table\n");
|
||||
|
||||
return 0;
|
||||
|
||||
error_alloc_segment:
|
||||
for (--i, --mhi_buf; i >= 0; i--, mhi_buf--)
|
||||
mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf,
|
||||
mhi_buf->dma_addr);
|
||||
|
||||
error_alloc_mhi_buf:
|
||||
kfree(img_info);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl,
|
||||
const struct firmware *firmware,
|
||||
struct image_info *img_info)
|
||||
{
|
||||
size_t remainder = firmware->size;
|
||||
size_t to_cpy;
|
||||
const u8 *buf = firmware->data;
|
||||
int i = 0;
|
||||
struct mhi_buf *mhi_buf = img_info->mhi_buf;
|
||||
struct bhi_vec_entry *bhi_vec = img_info->bhi_vec;
|
||||
|
||||
while (remainder) {
|
||||
MHI_ASSERT(i >= img_info->entries, "malformed vector table");
|
||||
|
||||
to_cpy = min(remainder, mhi_buf->len);
|
||||
memcpy(mhi_buf->buf, buf, to_cpy);
|
||||
bhi_vec->dma_addr = mhi_buf->dma_addr;
|
||||
bhi_vec->size = to_cpy;
|
||||
|
||||
MHI_VERB("Setting Vector:0x%llx size: %llu\n",
|
||||
bhi_vec->dma_addr, bhi_vec->size);
|
||||
buf += to_cpy;
|
||||
remainder -= to_cpy;
|
||||
i++;
|
||||
bhi_vec++;
|
||||
mhi_buf++;
|
||||
}
|
||||
}
|
||||
|
||||
void mhi_fw_load_worker(struct work_struct *work)
|
||||
{
|
||||
int ret;
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
const char *fw_name;
|
||||
const struct firmware *firmware;
|
||||
struct image_info *image_info;
|
||||
void *buf;
|
||||
size_t size;
|
||||
|
||||
mhi_cntrl = container_of(work, struct mhi_controller, fw_worker);
|
||||
|
||||
MHI_LOG("Waiting for device to enter PBL from EE:%s\n",
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_IN_PBL(mhi_cntrl->ee) ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
MHI_ERR("MHI is not in valid state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
MHI_LOG("Device current EE:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
/* if device in pthru, we do not have to load firmware */
|
||||
if (mhi_cntrl->ee == MHI_EE_PT)
|
||||
return;
|
||||
|
||||
fw_name = (mhi_cntrl->ee == MHI_EE_EDL) ?
|
||||
mhi_cntrl->edl_image : mhi_cntrl->fw_image;
|
||||
|
||||
if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size ||
|
||||
!mhi_cntrl->seg_len))) {
|
||||
MHI_ERR("No firmware image defined or !sbl_size || !seg_len\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = request_firmware(&firmware, fw_name, mhi_cntrl->dev);
|
||||
if (ret) {
|
||||
MHI_ERR("Error loading firmware, ret:%d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
size = (mhi_cntrl->fbc_download) ? mhi_cntrl->sbl_size : firmware->size;
|
||||
|
||||
/* the sbl size provided is maximum size, not necessarily image size */
|
||||
if (size > firmware->size)
|
||||
size = firmware->size;
|
||||
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
MHI_ERR("Could not allocate memory for image\n");
|
||||
release_firmware(firmware);
|
||||
return;
|
||||
}
|
||||
|
||||
/* load sbl image */
|
||||
memcpy(buf, firmware->data, size);
|
||||
ret = mhi_fw_load_sbl(mhi_cntrl, buf, size);
|
||||
kfree(buf);
|
||||
|
||||
if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL)
|
||||
release_firmware(firmware);
|
||||
|
||||
/* error or in edl, we're done */
|
||||
if (ret || mhi_cntrl->ee == MHI_EE_EDL)
|
||||
return;
|
||||
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
mhi_cntrl->dev_state = MHI_STATE_RESET;
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
|
||||
/*
|
||||
* if we're doing fbc, populate vector tables while
|
||||
* device transitioning into MHI READY state
|
||||
*/
|
||||
if (mhi_cntrl->fbc_download) {
|
||||
ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image,
|
||||
firmware->size);
|
||||
if (ret) {
|
||||
MHI_ERR("Error alloc size of %zu\n", firmware->size);
|
||||
goto error_alloc_fw_table;
|
||||
}
|
||||
|
||||
MHI_LOG("Copying firmware image into vector table\n");
|
||||
|
||||
/* load the firmware into BHIE vec table */
|
||||
mhi_firmware_copy(mhi_cntrl, firmware, mhi_cntrl->fbc_image);
|
||||
}
|
||||
|
||||
/* transitioning into MHI RESET->READY state */
|
||||
ret = mhi_ready_state_transition(mhi_cntrl);
|
||||
|
||||
MHI_LOG("To Reset->Ready PM_STATE:%s MHI_STATE:%s EE:%s, ret:%d\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state),
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee), ret);
|
||||
|
||||
if (!mhi_cntrl->fbc_download)
|
||||
return;
|
||||
|
||||
if (ret) {
|
||||
MHI_ERR("Did not transition to READY state\n");
|
||||
goto error_read;
|
||||
}
|
||||
|
||||
/* wait for BHIE event */
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_cntrl->ee == MHI_EE_BHIE ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
MHI_ERR("MHI did not enter BHIE\n");
|
||||
goto error_read;
|
||||
}
|
||||
|
||||
/* start full firmware image download */
|
||||
image_info = mhi_cntrl->fbc_image;
|
||||
ret = mhi_fw_load_amss(mhi_cntrl,
|
||||
/* last entry is vec table */
|
||||
&image_info->mhi_buf[image_info->entries - 1]);
|
||||
|
||||
MHI_LOG("amss fw_load, ret:%d\n", ret);
|
||||
|
||||
release_firmware(firmware);
|
||||
|
||||
return;
|
||||
|
||||
error_read:
|
||||
mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image);
|
||||
mhi_cntrl->fbc_image = NULL;
|
||||
|
||||
error_alloc_fw_table:
|
||||
release_firmware(firmware);
|
||||
}
|
||||
|
||||
int BhiWrite(struct mhi_controller *mhi_cntrl, void *buf, size_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
MHI_LOG("Device current EE:%s,%d M:%s\n",
|
||||
TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)),
|
||||
mhi_cntrl->ee,
|
||||
TO_MHI_STATE_STR(mhi_get_m_state(mhi_cntrl)));
|
||||
|
||||
mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
|
||||
|
||||
if (!MHI_IN_PBL(mhi_cntrl->ee)/* || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)*/) {
|
||||
MHI_ERR("MHI is not in valid BHI state:%d\n", mhi_cntrl->ee);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mhi_cntrl->ee != MHI_EE_EDL)
|
||||
return 0;
|
||||
|
||||
ret = mhi_fw_load_sbl(mhi_cntrl, buf, size);
|
||||
|
||||
if (ret) {
|
||||
MHI_ERR("ret = %d, ee=%d\n", ret, mhi_cntrl->ee);
|
||||
goto error_state;
|
||||
}
|
||||
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
mhi_cntrl->dev_state = MHI_STATE_RESET;
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
|
||||
/* transitioning into MHI RESET->READY state */
|
||||
ret = mhi_ready_state_transition(mhi_cntrl);
|
||||
if (ret) {
|
||||
MHI_ERR("Did not transition to READY state\n");
|
||||
goto error_state;
|
||||
}
|
||||
|
||||
MHI_LOG("To Reset->Ready PM_STATE:%s MHI_STATE:%s EE:%s, ret:%d\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state),
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee), ret);
|
||||
|
||||
/* wait for BHIE event */
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_cntrl->ee == MHI_EE_FP ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
MHI_ERR("MHI did not enter Flash Programmer Environment\n");
|
||||
goto error_state;
|
||||
}
|
||||
|
||||
MHI_LOG("MHI enter Flash Programmer Environment\n");
|
||||
return 0;
|
||||
|
||||
error_state:
|
||||
MHI_LOG("Device current EE:%s, M:%s\n",
|
||||
TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)),
|
||||
TO_MHI_STATE_STR(mhi_get_m_state(mhi_cntrl)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_cntrl_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mhi_cntrl_release(struct inode *inode, struct file *f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long mhi_cntrl_ioctl(struct file *f, unsigned int cmd, unsigned long __arg)
|
||||
{
|
||||
long ret = -EINVAL;
|
||||
void *ubuf = (void *)__arg;
|
||||
struct miscdevice *c = (struct miscdevice *)f->private_data;
|
||||
struct mhi_controller *mhi_cntrl = container_of(c, struct mhi_controller, miscdev);
|
||||
|
||||
switch (cmd) {
|
||||
case IOCTL_BHI_GETDEVINFO:
|
||||
{
|
||||
BHI_INFO_TYPE bhi_info;
|
||||
ret = BhiRead(mhi_cntrl, &bhi_info);
|
||||
if (ret) {
|
||||
MHI_ERR("IOCTL_BHI_GETDEVINFO BhiRead error, ret = %ld\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = copy_to_user(ubuf, &bhi_info, sizeof(bhi_info));
|
||||
if (ret) {
|
||||
MHI_ERR("IOCTL_BHI_GETDEVINFO copy error, ret = %ld\n", ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_BHI_WRITEIMAGE:
|
||||
{
|
||||
void *buf;
|
||||
size_t size;
|
||||
|
||||
ret = copy_from_user(&size, ubuf, sizeof(size));
|
||||
if (ret) {
|
||||
MHI_ERR("IOCTL_BHI_WRITEIMAGE copy size error, ret = %ld\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (buf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = copy_from_user(buf, ubuf+sizeof(size), size);
|
||||
if (ret) {
|
||||
MHI_ERR("IOCTL_BHI_WRITEIMAGE copy buf error, ret = %ld\n", ret);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = BhiWrite(mhi_cntrl, buf, size);
|
||||
if (ret) {
|
||||
MHI_ERR("IOCTL_BHI_WRITEIMAGE BhiWrite error, ret = %ld\n", ret);
|
||||
}
|
||||
kfree(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations mhi_cntrl_fops = {
|
||||
.unlocked_ioctl = mhi_cntrl_ioctl,
|
||||
.open = mhi_cntrl_open,
|
||||
.release = mhi_cntrl_release,
|
||||
};
|
||||
|
||||
int mhi_cntrl_register_miscdev(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
mhi_cntrl->miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
mhi_cntrl->miscdev.name = "mhi_BHI";
|
||||
mhi_cntrl->miscdev.fops = &mhi_cntrl_fops;
|
||||
|
||||
return misc_register(&mhi_cntrl->miscdev);
|
||||
}
|
||||
|
||||
void mhi_cntrl_deregister_miscdev(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
misc_deregister(&mhi_cntrl->miscdev);
|
||||
}
|
||||
@@ -1,362 +0,0 @@
|
||||
#ifndef __MHI_COMMON_H
|
||||
#define __MHI_COMMON_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* MHI control data structures alloted by the host, including
|
||||
* channel context array, event context array, command context and rings */
|
||||
|
||||
/* Channel context state */
|
||||
enum mhi_dev_ch_ctx_state {
|
||||
MHI_DEV_CH_STATE_DISABLED,
|
||||
MHI_DEV_CH_STATE_ENABLED,
|
||||
MHI_DEV_CH_STATE_RUNNING,
|
||||
MHI_DEV_CH_STATE_SUSPENDED,
|
||||
MHI_DEV_CH_STATE_STOP,
|
||||
MHI_DEV_CH_STATE_ERROR,
|
||||
MHI_DEV_CH_STATE_RESERVED,
|
||||
MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/* Channel type */
|
||||
enum mhi_dev_ch_ctx_type {
|
||||
MHI_DEV_CH_TYPE_NONE,
|
||||
MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL,
|
||||
MHI_DEV_CH_TYPE_INBOUND_CHANNEL,
|
||||
MHI_DEV_CH_RESERVED
|
||||
};
|
||||
|
||||
/* Channel context type */
|
||||
struct mhi_dev_ch_ctx {
|
||||
enum mhi_dev_ch_ctx_state ch_state;
|
||||
enum mhi_dev_ch_ctx_type ch_type;
|
||||
uint32_t err_indx;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_ring_element_type_id {
|
||||
MHI_DEV_RING_EL_INVALID = 0,
|
||||
MHI_DEV_RING_EL_NOOP = 1,
|
||||
MHI_DEV_RING_EL_TRANSFER = 2,
|
||||
MHI_DEV_RING_EL_RESET = 16,
|
||||
MHI_DEV_RING_EL_STOP = 17,
|
||||
MHI_DEV_RING_EL_START = 18,
|
||||
MHI_DEV_RING_EL_MHI_STATE_CHG = 32,
|
||||
MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33,
|
||||
MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34,
|
||||
MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64,
|
||||
MHI_DEV_RING_EL_UNDEF
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_state {
|
||||
RING_STATE_UINT = 0,
|
||||
RING_STATE_IDLE,
|
||||
RING_STATE_PENDING,
|
||||
};
|
||||
|
||||
enum mhi_dev_ring_type {
|
||||
RING_TYPE_CMD = 0,
|
||||
RING_TYPE_ER,
|
||||
RING_TYPE_CH,
|
||||
RING_TYPE_INVAL
|
||||
};
|
||||
|
||||
/* Event context interrupt moderation */
|
||||
enum mhi_dev_evt_ctx_int_mod_timer {
|
||||
MHI_DEV_EVT_INT_MODERATION_DISABLED
|
||||
};
|
||||
|
||||
/* Event ring type */
|
||||
enum mhi_dev_evt_ctx_event_ring_type {
|
||||
MHI_DEV_EVT_TYPE_DEFAULT,
|
||||
MHI_DEV_EVT_TYPE_VALID,
|
||||
MHI_DEV_EVT_RESERVED
|
||||
};
|
||||
|
||||
/* Event ring context type */
|
||||
struct mhi_dev_ev_ctx {
|
||||
uint32_t res1:16;
|
||||
enum mhi_dev_evt_ctx_int_mod_timer intmodt:16;
|
||||
enum mhi_dev_evt_ctx_event_ring_type ertype;
|
||||
uint32_t msivec;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Command context */
|
||||
struct mhi_dev_cmd_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* generic context */
|
||||
struct mhi_dev_gen_ctx {
|
||||
uint32_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3;
|
||||
uint64_t rbase;
|
||||
uint64_t rlen;
|
||||
uint64_t rp;
|
||||
uint64_t wp;
|
||||
} __packed;
|
||||
|
||||
/* Transfer ring element */
|
||||
struct mhi_dev_transfer_ring_element {
|
||||
uint64_t data_buf_ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:16;
|
||||
uint32_t chain:1;
|
||||
uint32_t res2:7;
|
||||
uint32_t ieob:1;
|
||||
uint32_t ieot:1;
|
||||
uint32_t bei:1;
|
||||
uint32_t res3:5;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res4:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring element */
|
||||
/* Command ring No op command */
|
||||
struct mhi_dev_cmd_ring_op {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring reset channel command */
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring stop channel command */
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t res2;
|
||||
uint32_t res3:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command ring start channel command */
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd {
|
||||
uint64_t res1;
|
||||
uint32_t seqnum;
|
||||
uint32_t reliable:1;
|
||||
uint32_t res2:15;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_cmd_completion_code {
|
||||
MHI_CMD_COMPL_CODE_INVALID = 0,
|
||||
MHI_CMD_COMPL_CODE_SUCCESS = 1,
|
||||
MHI_CMD_COMPL_CODE_EOT = 2,
|
||||
MHI_CMD_COMPL_CODE_OVERFLOW = 3,
|
||||
MHI_CMD_COMPL_CODE_EOB = 4,
|
||||
MHI_CMD_COMPL_CODE_UNDEFINED = 16,
|
||||
MHI_CMD_COMPL_CODE_RING_EL = 17,
|
||||
MHI_CMD_COMPL_CODE_RES
|
||||
};
|
||||
|
||||
/* Event ring elements */
|
||||
/* Transfer completion event */
|
||||
struct mhi_dev_event_ring_transfer_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t len:16;
|
||||
uint32_t res1:8;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
/* Command completion event */
|
||||
struct mhi_dev_event_ring_cmd_completion {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_cmd_completion_code code:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_state {
|
||||
MHI_DEV_RESET_STATE = 0,
|
||||
MHI_DEV_READY_STATE,
|
||||
MHI_DEV_M0_STATE,
|
||||
MHI_DEV_M1_STATE,
|
||||
MHI_DEV_M2_STATE,
|
||||
MHI_DEV_M3_STATE,
|
||||
MHI_DEV_MAX_STATE,
|
||||
MHI_DEV_SYSERR_STATE = 0xff
|
||||
};
|
||||
|
||||
/* MHI state change event */
|
||||
struct mhi_dev_event_ring_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
enum mhi_dev_execenv {
|
||||
MHI_DEV_SBL_EE = 1,
|
||||
MHI_DEV_AMSS_EE = 2,
|
||||
MHI_DEV_UNRESERVED
|
||||
};
|
||||
|
||||
/* EE state change event */
|
||||
struct mhi_dev_event_ring_ee_state_change {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_execenv execenv:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t res3:8;
|
||||
} __packed;
|
||||
|
||||
/* Generic cmd to parse common details like type and channel id */
|
||||
struct mhi_dev_ring_generic {
|
||||
uint64_t ptr;
|
||||
uint32_t res1:24;
|
||||
enum mhi_dev_state mhistate:8;
|
||||
uint32_t res2:16;
|
||||
enum mhi_dev_ring_element_type_id type:8;
|
||||
uint32_t chid:8;
|
||||
} __packed;
|
||||
|
||||
struct mhi_config {
|
||||
uint32_t mhi_reg_len;
|
||||
uint32_t version;
|
||||
uint32_t event_rings;
|
||||
uint32_t channels;
|
||||
uint32_t chdb_offset;
|
||||
uint32_t erdb_offset;
|
||||
};
|
||||
|
||||
#define NUM_CHANNELS 128
|
||||
#define HW_CHANNEL_BASE 100
|
||||
#define HW_CHANNEL_END 107
|
||||
#define MHI_ENV_VALUE 2
|
||||
#define MHI_MASK_ROWS_CH_EV_DB 4
|
||||
#define TRB_MAX_DATA_SIZE 8192
|
||||
#define MHI_CTRL_STATE 25
|
||||
#define IPA_DMA_SYNC 1
|
||||
#define IPA_DMA_ASYNC 0
|
||||
|
||||
/*maximum trasnfer completion events buffer*/
|
||||
#define MAX_TR_EVENTS 50
|
||||
/*maximum event requests */
|
||||
#define MHI_MAX_EVT_REQ 50
|
||||
|
||||
/* Possible ring element types */
|
||||
union mhi_dev_ring_element_type {
|
||||
struct mhi_dev_cmd_ring_op cmd_no_op;
|
||||
struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset;
|
||||
struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop;
|
||||
struct mhi_dev_cmd_ring_start_channel_cmd cmd_start;
|
||||
struct mhi_dev_transfer_ring_element tre;
|
||||
struct mhi_dev_event_ring_transfer_completion evt_tr_comp;
|
||||
struct mhi_dev_event_ring_cmd_completion evt_cmd_comp;
|
||||
struct mhi_dev_event_ring_state_change evt_state_change;
|
||||
struct mhi_dev_event_ring_ee_state_change evt_ee_state;
|
||||
struct mhi_dev_ring_generic generic;
|
||||
};
|
||||
|
||||
/* Transfer ring element type */
|
||||
union mhi_dev_ring_ctx {
|
||||
struct mhi_dev_cmd_ctx cmd;
|
||||
struct mhi_dev_ev_ctx ev;
|
||||
struct mhi_dev_ch_ctx ch;
|
||||
struct mhi_dev_gen_ctx generic;
|
||||
};
|
||||
|
||||
/* MHI host Control and data address region */
|
||||
struct mhi_host_addr {
|
||||
uint32_t ctrl_base_lsb;
|
||||
uint32_t ctrl_base_msb;
|
||||
uint32_t ctrl_limit_lsb;
|
||||
uint32_t ctrl_limit_msb;
|
||||
uint32_t data_base_lsb;
|
||||
uint32_t data_base_msb;
|
||||
uint32_t data_limit_lsb;
|
||||
uint32_t data_limit_msb;
|
||||
};
|
||||
|
||||
/* MHI physical and virtual address region */
|
||||
struct mhi_meminfo {
|
||||
struct device *dev;
|
||||
uintptr_t pa_aligned;
|
||||
uintptr_t pa_unaligned;
|
||||
uintptr_t va_aligned;
|
||||
uintptr_t va_unaligned;
|
||||
uintptr_t size;
|
||||
};
|
||||
|
||||
struct mhi_addr {
|
||||
uint64_t host_pa;
|
||||
uintptr_t device_pa;
|
||||
uintptr_t device_va;
|
||||
size_t size;
|
||||
dma_addr_t phy_addr;
|
||||
void *virt_addr;
|
||||
bool use_ipa_dma;
|
||||
};
|
||||
|
||||
struct mhi_interrupt_state {
|
||||
uint32_t mask;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
enum mhi_dev_channel_state {
|
||||
MHI_DEV_CH_UNINT,
|
||||
MHI_DEV_CH_STARTED,
|
||||
MHI_DEV_CH_PENDING_START,
|
||||
MHI_DEV_CH_PENDING_STOP,
|
||||
MHI_DEV_CH_STOPPED,
|
||||
MHI_DEV_CH_CLOSED,
|
||||
};
|
||||
|
||||
enum mhi_dev_ch_operation {
|
||||
MHI_DEV_OPEN_CH,
|
||||
MHI_DEV_CLOSE_CH,
|
||||
MHI_DEV_READ_CH,
|
||||
MHI_DEV_READ_WR,
|
||||
MHI_DEV_POLL,
|
||||
};
|
||||
|
||||
enum mhi_ctrl_info {
|
||||
MHI_STATE_CONFIGURED = 0,
|
||||
MHI_STATE_CONNECTED = 1,
|
||||
MHI_STATE_DISCONNECTED = 2,
|
||||
MHI_STATE_INVAL,
|
||||
};
|
||||
|
||||
enum mhi_dev_tr_compl_evt_type {
|
||||
SEND_EVENT_BUFFER,
|
||||
SEND_EVENT_RD_OFFSET,
|
||||
};
|
||||
|
||||
enum mhi_dev_transfer_type {
|
||||
MHI_DEV_DMA_SYNC,
|
||||
MHI_DEV_DMA_ASYNC,
|
||||
};
|
||||
#endif /* _MHI_COMMON_H_ */
|
||||
@@ -1,181 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/termios.h>
|
||||
#include <linux/wait.h>
|
||||
#include "mhi.h"
|
||||
#include "mhi_internal.h"
|
||||
|
||||
struct __packed dtr_ctrl_msg {
|
||||
u32 preamble;
|
||||
u32 msg_id;
|
||||
u32 dest_id;
|
||||
u32 size;
|
||||
u32 msg;
|
||||
};
|
||||
|
||||
#define CTRL_MAGIC (0x4C525443)
|
||||
#define CTRL_MSG_DTR BIT(0)
|
||||
#define CTRL_MSG_ID (0x10)
|
||||
|
||||
static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan,
|
||||
u32 tiocm)
|
||||
{
|
||||
struct dtr_ctrl_msg *dtr_msg = NULL;
|
||||
struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan;
|
||||
int ret = 0;
|
||||
|
||||
tiocm &= TIOCM_DTR;
|
||||
if (mhi_chan->tiocm == tiocm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&dtr_chan->mutex);
|
||||
|
||||
dtr_msg = kzalloc(sizeof(*dtr_msg), GFP_KERNEL);
|
||||
if (!dtr_msg) {
|
||||
ret = -ENOMEM;
|
||||
goto tiocm_exit;
|
||||
}
|
||||
|
||||
dtr_msg->preamble = CTRL_MAGIC;
|
||||
dtr_msg->msg_id = CTRL_MSG_ID;
|
||||
dtr_msg->dest_id = mhi_chan->chan;
|
||||
dtr_msg->size = sizeof(u32);
|
||||
if (tiocm & TIOCM_DTR)
|
||||
dtr_msg->msg |= CTRL_MSG_DTR;
|
||||
|
||||
reinit_completion(&dtr_chan->completion);
|
||||
ret = mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_TO_DEVICE, dtr_msg,
|
||||
sizeof(*dtr_msg), MHI_EOT);
|
||||
if (ret)
|
||||
goto tiocm_exit;
|
||||
|
||||
ret = wait_for_completion_timeout(&dtr_chan->completion,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret) {
|
||||
MHI_ERR("Failed to receive transfer callback\n");
|
||||
ret = -EIO;
|
||||
goto tiocm_exit;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
mhi_chan->tiocm = tiocm;
|
||||
|
||||
tiocm_exit:
|
||||
kfree(dtr_msg);
|
||||
mutex_unlock(&dtr_chan->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
struct mhi_chan *mhi_chan = mhi_dev->ul_chan;
|
||||
int ret;
|
||||
|
||||
/* ioctl not supported by this controller */
|
||||
if (!mhi_cntrl->dtr_dev)
|
||||
return -EIO;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCMGET:
|
||||
return mhi_chan->tiocm;
|
||||
case TIOCMSET:
|
||||
{
|
||||
u32 tiocm;
|
||||
|
||||
ret = get_user(tiocm, (u32 *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mhi_dtr_tiocmset(mhi_cntrl, mhi_chan, tiocm);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_ioctl);
|
||||
|
||||
static void mhi_dtr_xfer_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan;
|
||||
|
||||
MHI_VERB("Received with status:%d\n", mhi_result->transaction_status);
|
||||
if (!mhi_result->transaction_status)
|
||||
complete(&dtr_chan->completion);
|
||||
}
|
||||
|
||||
static void mhi_dtr_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
|
||||
mhi_cntrl->dtr_dev = NULL;
|
||||
}
|
||||
|
||||
static int mhi_dtr_probe(struct mhi_device *mhi_dev,
|
||||
const struct mhi_device_id *id)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
int ret;
|
||||
|
||||
MHI_LOG("Enter for DTR control channel\n");
|
||||
|
||||
ret = mhi_prepare_for_transfer(mhi_dev);
|
||||
if (!ret)
|
||||
mhi_cntrl->dtr_dev = mhi_dev;
|
||||
|
||||
MHI_LOG("Exit with ret:%d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct mhi_device_id mhi_dtr_table[] = {
|
||||
{ .chan = "IP_CTRL" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct mhi_driver mhi_dtr_driver = {
|
||||
.id_table = mhi_dtr_table,
|
||||
.remove = mhi_dtr_remove,
|
||||
.probe = mhi_dtr_probe,
|
||||
.ul_xfer_cb = mhi_dtr_xfer_cb,
|
||||
.dl_xfer_cb = mhi_dtr_xfer_cb,
|
||||
.driver = {
|
||||
.name = "MHI_DTR",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
int __init mhi_dtr_init(void)
|
||||
{
|
||||
return mhi_driver_register(&mhi_dtr_driver);
|
||||
}
|
||||
|
||||
void mhi_dtr_exit(void) {
|
||||
mhi_driver_unregister(&mhi_dtr_driver);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,800 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _MHI_INT_H
|
||||
#define _MHI_INT_H
|
||||
|
||||
#include <linux/version.h>
|
||||
#ifndef writel_relaxed
|
||||
#define writel_relaxed writel
|
||||
#endif
|
||||
|
||||
#ifndef U32_MAX
|
||||
#define U32_MAX ((u32)~0U)
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 ))
|
||||
static inline void reinit_completion(struct completion *x)
|
||||
{
|
||||
x->done = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern struct bus_type mhi_bus_type;
|
||||
|
||||
/* MHI mmio register mapping */
|
||||
#define PCI_INVALID_READ(val) (val == U32_MAX)
|
||||
|
||||
#define MHIREGLEN (0x0)
|
||||
#define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF)
|
||||
#define MHIREGLEN_MHIREGLEN_SHIFT (0)
|
||||
|
||||
#define MHIVER (0x8)
|
||||
#define MHIVER_MHIVER_MASK (0xFFFFFFFF)
|
||||
#define MHIVER_MHIVER_SHIFT (0)
|
||||
|
||||
#define MHICFG (0x10)
|
||||
#define MHICFG_NHWER_MASK (0xFF000000)
|
||||
#define MHICFG_NHWER_SHIFT (24)
|
||||
#define MHICFG_NER_MASK (0xFF0000)
|
||||
#define MHICFG_NER_SHIFT (16)
|
||||
#define MHICFG_NHWCH_MASK (0xFF00)
|
||||
#define MHICFG_NHWCH_SHIFT (8)
|
||||
#define MHICFG_NCH_MASK (0xFF)
|
||||
#define MHICFG_NCH_SHIFT (0)
|
||||
|
||||
#define CHDBOFF (0x18)
|
||||
#define CHDBOFF_CHDBOFF_MASK (0xFFFFFFFF)
|
||||
#define CHDBOFF_CHDBOFF_SHIFT (0)
|
||||
|
||||
#define ERDBOFF (0x20)
|
||||
#define ERDBOFF_ERDBOFF_MASK (0xFFFFFFFF)
|
||||
#define ERDBOFF_ERDBOFF_SHIFT (0)
|
||||
|
||||
#define BHIOFF (0x28)
|
||||
#define BHIOFF_BHIOFF_MASK (0xFFFFFFFF)
|
||||
#define BHIOFF_BHIOFF_SHIFT (0)
|
||||
|
||||
#define DEBUGOFF (0x30)
|
||||
#define DEBUGOFF_DEBUGOFF_MASK (0xFFFFFFFF)
|
||||
#define DEBUGOFF_DEBUGOFF_SHIFT (0)
|
||||
|
||||
#define MHICTRL (0x38)
|
||||
#define MHICTRL_MHISTATE_MASK (0x0000FF00)
|
||||
#define MHICTRL_MHISTATE_SHIFT (8)
|
||||
#define MHICTRL_RESET_MASK (0x2)
|
||||
#define MHICTRL_RESET_SHIFT (1)
|
||||
|
||||
#define MHISTATUS (0x48)
|
||||
#define MHISTATUS_MHISTATE_MASK (0x0000FF00)
|
||||
#define MHISTATUS_MHISTATE_SHIFT (8)
|
||||
#define MHISTATUS_SYSERR_MASK (0x4)
|
||||
#define MHISTATUS_SYSERR_SHIFT (2)
|
||||
#define MHISTATUS_READY_MASK (0x1)
|
||||
#define MHISTATUS_READY_SHIFT (0)
|
||||
|
||||
#define CCABAP_LOWER (0x58)
|
||||
#define CCABAP_LOWER_CCABAP_LOWER_MASK (0xFFFFFFFF)
|
||||
#define CCABAP_LOWER_CCABAP_LOWER_SHIFT (0)
|
||||
|
||||
#define CCABAP_HIGHER (0x5C)
|
||||
#define CCABAP_HIGHER_CCABAP_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define CCABAP_HIGHER_CCABAP_HIGHER_SHIFT (0)
|
||||
|
||||
#define ECABAP_LOWER (0x60)
|
||||
#define ECABAP_LOWER_ECABAP_LOWER_MASK (0xFFFFFFFF)
|
||||
#define ECABAP_LOWER_ECABAP_LOWER_SHIFT (0)
|
||||
|
||||
#define ECABAP_HIGHER (0x64)
|
||||
#define ECABAP_HIGHER_ECABAP_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define ECABAP_HIGHER_ECABAP_HIGHER_SHIFT (0)
|
||||
|
||||
#define CRCBAP_LOWER (0x68)
|
||||
#define CRCBAP_LOWER_CRCBAP_LOWER_MASK (0xFFFFFFFF)
|
||||
#define CRCBAP_LOWER_CRCBAP_LOWER_SHIFT (0)
|
||||
|
||||
#define CRCBAP_HIGHER (0x6C)
|
||||
#define CRCBAP_HIGHER_CRCBAP_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define CRCBAP_HIGHER_CRCBAP_HIGHER_SHIFT (0)
|
||||
|
||||
#define CRDB_LOWER (0x70)
|
||||
#define CRDB_LOWER_CRDB_LOWER_MASK (0xFFFFFFFF)
|
||||
#define CRDB_LOWER_CRDB_LOWER_SHIFT (0)
|
||||
|
||||
#define CRDB_HIGHER (0x74)
|
||||
#define CRDB_HIGHER_CRDB_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define CRDB_HIGHER_CRDB_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHICTRLBASE_LOWER (0x80)
|
||||
#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_SHIFT (0)
|
||||
|
||||
#define MHICTRLBASE_HIGHER (0x84)
|
||||
#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHICTRLLIMIT_LOWER (0x88)
|
||||
#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_SHIFT (0)
|
||||
|
||||
#define MHICTRLLIMIT_HIGHER (0x8C)
|
||||
#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHIDATABASE_LOWER (0x98)
|
||||
#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_SHIFT (0)
|
||||
|
||||
#define MHIDATABASE_HIGHER (0x9C)
|
||||
#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_SHIFT (0)
|
||||
|
||||
#define MHIDATALIMIT_LOWER (0xA0)
|
||||
#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_SHIFT (0)
|
||||
|
||||
#define MHIDATALIMIT_HIGHER (0xA4)
|
||||
#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK (0xFFFFFFFF)
|
||||
#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT (0)
|
||||
|
||||
/* MHI BHI offfsets */
|
||||
#define BHI_BHIVERSION_MINOR (0x00)
|
||||
#define BHI_BHIVERSION_MAJOR (0x04)
|
||||
#define BHI_IMGADDR_LOW (0x08)
|
||||
#define BHI_IMGADDR_HIGH (0x0C)
|
||||
#define BHI_IMGSIZE (0x10)
|
||||
#define BHI_RSVD1 (0x14)
|
||||
#define BHI_IMGTXDB (0x18)
|
||||
#define BHI_TXDB_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHI_TXDB_SEQNUM_SHFT (0)
|
||||
#define BHI_RSVD2 (0x1C)
|
||||
#define BHI_INTVEC (0x20)
|
||||
#define BHI_RSVD3 (0x24)
|
||||
#define BHI_EXECENV (0x28)
|
||||
#define BHI_STATUS (0x2C)
|
||||
#define BHI_ERRCODE (0x30)
|
||||
#define BHI_ERRDBG1 (0x34)
|
||||
#define BHI_ERRDBG2 (0x38)
|
||||
#define BHI_ERRDBG3 (0x3C)
|
||||
#define BHI_SERIALNUM ( 0x40 )
|
||||
#define BHI_SERIALNU (0x40)
|
||||
#define BHI_SBLANTIROLLVER (0x44)
|
||||
#define BHI_NUMSEG (0x48)
|
||||
#define BHI_MSMHWID(n) (0x4C + (0x4 * n))
|
||||
#define BHI_OEMPKHASH(n) (0x64 + (0x4 * n))
|
||||
#define BHI_RSVD5 (0xC4)
|
||||
#define BHI_STATUS_MASK (0xC0000000)
|
||||
#define BHI_STATUS_SHIFT (30)
|
||||
#define BHI_STATUS_ERROR (3)
|
||||
#define BHI_STATUS_SUCCESS (2)
|
||||
#define BHI_STATUS_RESET (0)
|
||||
|
||||
/* MHI BHIE offsets */
|
||||
#define BHIE_OFFSET (0x0124) /* BHIE register space offset from BHI base */
|
||||
#define BHIE_MSMSOCID_OFFS (BHIE_OFFSET + 0x0000)
|
||||
#define BHIE_TXVECADDR_LOW_OFFS (BHIE_OFFSET + 0x002C)
|
||||
#define BHIE_TXVECADDR_HIGH_OFFS (BHIE_OFFSET + 0x0030)
|
||||
#define BHIE_TXVECSIZE_OFFS (BHIE_OFFSET + 0x0034)
|
||||
#define BHIE_TXVECDB_OFFS (BHIE_OFFSET + 0x003C)
|
||||
#define BHIE_TXVECDB_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_TXVECDB_SEQNUM_SHFT (0)
|
||||
#define BHIE_TXVECSTATUS_OFFS (BHIE_OFFSET + 0x0044)
|
||||
#define BHIE_TXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_TXVECSTATUS_SEQNUM_SHFT (0)
|
||||
#define BHIE_TXVECSTATUS_STATUS_BMSK (0xC0000000)
|
||||
#define BHIE_TXVECSTATUS_STATUS_SHFT (30)
|
||||
#define BHIE_TXVECSTATUS_STATUS_RESET (0x00)
|
||||
#define BHIE_TXVECSTATUS_STATUS_XFER_COMPL (0x02)
|
||||
#define BHIE_TXVECSTATUS_STATUS_ERROR (0x03)
|
||||
#define BHIE_RXVECADDR_LOW_OFFS (BHIE_OFFSET + 0x0060)
|
||||
#define BHIE_RXVECADDR_HIGH_OFFS (BHIE_OFFSET + 0x0064)
|
||||
#define BHIE_RXVECSIZE_OFFS (BHIE_OFFSET + 0x0068)
|
||||
#define BHIE_RXVECDB_OFFS (BHIE_OFFSET + 0x0070)
|
||||
#define BHIE_RXVECDB_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_RXVECDB_SEQNUM_SHFT (0)
|
||||
#define BHIE_RXVECSTATUS_OFFS (BHIE_OFFSET + 0x0078)
|
||||
#define BHIE_RXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF)
|
||||
#define BHIE_RXVECSTATUS_SEQNUM_SHFT (0)
|
||||
#define BHIE_RXVECSTATUS_STATUS_BMSK (0xC0000000)
|
||||
#define BHIE_RXVECSTATUS_STATUS_SHFT (30)
|
||||
#define BHIE_RXVECSTATUS_STATUS_RESET (0x00)
|
||||
#define BHIE_RXVECSTATUS_STATUS_XFER_COMPL (0x02)
|
||||
#define BHIE_RXVECSTATUS_STATUS_ERROR (0x03)
|
||||
|
||||
struct __packed mhi_event_ctxt {
|
||||
u32 reserved : 8;
|
||||
u32 intmodc : 8;
|
||||
u32 intmodt : 16;
|
||||
u32 ertype;
|
||||
u32 msivec;
|
||||
u64 rbase;
|
||||
u64 rlen;
|
||||
u64 rp;
|
||||
u64 wp;
|
||||
};
|
||||
|
||||
struct __packed mhi_chan_ctxt {
|
||||
u32 chstate : 8;
|
||||
u32 brstmode : 2;
|
||||
u32 pollcfg : 6;
|
||||
u32 reserved : 16;
|
||||
u32 chtype;
|
||||
u32 erindex;
|
||||
u64 rbase;
|
||||
u64 rlen;
|
||||
u64 rp;
|
||||
u64 wp;
|
||||
};
|
||||
|
||||
struct __packed mhi_cmd_ctxt {
|
||||
u32 reserved0;
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
u64 rbase;
|
||||
u64 rlen;
|
||||
u64 rp;
|
||||
u64 wp;
|
||||
};
|
||||
|
||||
struct __packed mhi_tre {
|
||||
u64 ptr;
|
||||
u32 dword[2];
|
||||
};
|
||||
|
||||
struct __packed bhi_vec_entry {
|
||||
u64 dma_addr;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
/* no operation command */
|
||||
#define MHI_TRE_CMD_NOOP_PTR cpu_to_le64(0)
|
||||
#define MHI_TRE_CMD_NOOP_DWORD0 cpu_to_le32(0)
|
||||
#define MHI_TRE_CMD_NOOP_DWORD1 cpu_to_le32(1 << 16)
|
||||
|
||||
/* channel reset command */
|
||||
#define MHI_TRE_CMD_RESET_PTR cpu_to_le64(0)
|
||||
#define MHI_TRE_CMD_RESET_DWORD0 cpu_to_le32(0)
|
||||
#define MHI_TRE_CMD_RESET_DWORD1(chid) cpu_to_le32((chid << 24) | (16 << 16))
|
||||
|
||||
/* channel stop command */
|
||||
#define MHI_TRE_CMD_STOP_PTR cpu_to_le64(0)
|
||||
#define MHI_TRE_CMD_STOP_DWORD0 cpu_to_le32(0)
|
||||
#define MHI_TRE_CMD_STOP_DWORD1(chid) cpu_to_le32((chid << 24) | (17 << 16))
|
||||
|
||||
/* channel start command */
|
||||
#define MHI_TRE_CMD_START_PTR cpu_to_le64(0)
|
||||
#define MHI_TRE_CMD_START_DWORD0 cpu_to_le32(0)
|
||||
#define MHI_TRE_CMD_START_DWORD1(chid) cpu_to_le32((chid << 24) | (18 << 16))
|
||||
|
||||
#define MHI_TRE_GET_CMD_CHID(tre) ((le32_to_cpu((tre)->dword[1]) >> 24) & 0xFF)
|
||||
|
||||
/* event descriptor macros */
|
||||
//#define MHI_TRE_EV_PTR(ptr) (ptr)
|
||||
//#define MHI_TRE_EV_DWORD0(code, len) ((code << 24) | len)
|
||||
#define MHI_TRE_EV_DWORD1(chid, type) cpu_to_le32((chid << 24) | (type << 16))
|
||||
#define MHI_TRE_GET_EV_PTR(tre) le64_to_cpu((tre)->ptr)
|
||||
#define MHI_TRE_GET_EV_CODE(tre) ((le32_to_cpu((tre)->dword[0]) >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_LEN(tre) (le32_to_cpu((tre)->dword[0]) & 0xFFFF)
|
||||
#define MHI_TRE_GET_EV_CHID(tre) ((le32_to_cpu((tre)->dword[1]) >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_TYPE(tre) ((le32_to_cpu((tre)->dword[1]) >> 16) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_STATE(tre) ((le32_to_cpu((tre)->dword[0]) >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_EV_EXECENV(tre) ((le32_to_cpu((tre)->dword[0]) >> 24) & 0xFF)
|
||||
|
||||
|
||||
/* transfer descriptor macros */
|
||||
#define MHI_TRE_DATA_PTR(ptr) cpu_to_le64(ptr)
|
||||
#define MHI_TRE_DATA_DWORD0(len) cpu_to_le32(len & MHI_MAX_MTU)
|
||||
#define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) cpu_to_le32((2 << 16) | (bei << 10) \
|
||||
| (ieot << 9) | (ieob << 8) | chain)
|
||||
|
||||
enum MHI_CMD {
|
||||
MHI_CMD_NOOP = 0x0,
|
||||
MHI_CMD_RESET_CHAN = 0x1,
|
||||
MHI_CMD_STOP_CHAN = 0x2,
|
||||
MHI_CMD_START_CHAN = 0x3,
|
||||
MHI_CMD_RESUME_CHAN = 0x4,
|
||||
};
|
||||
|
||||
enum MHI_PKT_TYPE {
|
||||
MHI_PKT_TYPE_INVALID = 0x0,
|
||||
MHI_PKT_TYPE_NOOP_CMD = 0x1,
|
||||
MHI_PKT_TYPE_TRANSFER = 0x2,
|
||||
MHI_PKT_TYPE_RESET_CHAN_CMD = 0x10,
|
||||
MHI_PKT_TYPE_STOP_CHAN_CMD = 0x11,
|
||||
MHI_PKT_TYPE_START_CHAN_CMD = 0x12,
|
||||
MHI_PKT_TYPE_STATE_CHANGE_EVENT = 0x20,
|
||||
MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21,
|
||||
MHI_PKT_TYPE_TX_EVENT = 0x22,
|
||||
MHI_PKT_TYPE_EE_EVENT = 0x40,
|
||||
MHI_PKT_TYPE_STALE_EVENT, /* internal event */
|
||||
};
|
||||
|
||||
/* MHI transfer completion events */
|
||||
enum MHI_EV_CCS {
|
||||
MHI_EV_CC_INVALID = 0x0,
|
||||
MHI_EV_CC_SUCCESS = 0x1,
|
||||
MHI_EV_CC_EOT = 0x2,
|
||||
MHI_EV_CC_OVERFLOW = 0x3,
|
||||
MHI_EV_CC_EOB = 0x4,
|
||||
MHI_EV_CC_OOB = 0x5,
|
||||
MHI_EV_CC_DB_MODE = 0x6,
|
||||
MHI_EV_CC_UNDEFINED_ERR = 0x10,
|
||||
MHI_EV_CC_BAD_TRE = 0x11,
|
||||
};
|
||||
|
||||
enum MHI_CH_STATE {
|
||||
MHI_CH_STATE_DISABLED = 0x0,
|
||||
MHI_CH_STATE_ENABLED = 0x1,
|
||||
MHI_CH_STATE_RUNNING = 0x2,
|
||||
MHI_CH_STATE_SUSPENDED = 0x3,
|
||||
MHI_CH_STATE_STOP = 0x4,
|
||||
MHI_CH_STATE_ERROR = 0x5,
|
||||
};
|
||||
|
||||
enum MHI_CH_CFG {
|
||||
MHI_CH_CFG_CHAN_ID = 0,
|
||||
MHI_CH_CFG_ELEMENTS = 1,
|
||||
MHI_CH_CFG_ER_INDEX = 2,
|
||||
MHI_CH_CFG_DIRECTION = 3,
|
||||
MHI_CH_CFG_BRSTMODE = 4,
|
||||
MHI_CH_CFG_POLLCFG = 5,
|
||||
MHI_CH_CFG_EE = 6,
|
||||
MHI_CH_CFG_XFER_TYPE = 7,
|
||||
MHI_CH_CFG_BITCFG = 8,
|
||||
MHI_CH_CFG_MAX
|
||||
};
|
||||
|
||||
#define MHI_CH_CFG_BIT_LPM_NOTIFY BIT(0) /* require LPM notification */
|
||||
#define MHI_CH_CFG_BIT_OFFLOAD_CH BIT(1) /* satellite mhi devices */
|
||||
#define MHI_CH_CFG_BIT_DBMODE_RESET_CH BIT(2) /* require db mode to reset */
|
||||
#define MHI_CH_CFG_BIT_PRE_ALLOC BIT(3) /* host allocate buffers for DL */
|
||||
|
||||
enum MHI_EV_CFG {
|
||||
MHI_EV_CFG_ELEMENTS = 0,
|
||||
MHI_EV_CFG_INTMOD = 1,
|
||||
MHI_EV_CFG_MSI = 2,
|
||||
MHI_EV_CFG_CHAN = 3,
|
||||
MHI_EV_CFG_PRIORITY = 4,
|
||||
MHI_EV_CFG_BRSTMODE = 5,
|
||||
MHI_EV_CFG_BITCFG = 6,
|
||||
MHI_EV_CFG_MAX
|
||||
};
|
||||
|
||||
#define MHI_EV_CFG_BIT_HW_EV BIT(0) /* hw event ring */
|
||||
#define MHI_EV_CFG_BIT_CL_MANAGE BIT(1) /* client manages the event ring */
|
||||
#define MHI_EV_CFG_BIT_OFFLOAD_EV BIT(2) /* satellite driver manges it */
|
||||
#define MHI_EV_CFG_BIT_CTRL_EV BIT(3) /* ctrl event ring */
|
||||
|
||||
enum MHI_BRSTMODE {
|
||||
MHI_BRSTMODE_DISABLE = 0x2,
|
||||
MHI_BRSTMODE_ENABLE = 0x3,
|
||||
};
|
||||
|
||||
#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_BRSTMODE_DISABLE && \
|
||||
mode != MHI_BRSTMODE_ENABLE)
|
||||
|
||||
enum MHI_EE {
|
||||
MHI_EE_PBL = 0x0, /* Primary Boot Loader */
|
||||
MHI_EE_SBL = 0x1, /* Secondary Boot Loader */
|
||||
MHI_EE_AMSS = 0x2, /* AMSS Firmware */
|
||||
MHI_EE_RDDM = 0x3, /* WIFI Ram Dump Debug Module */
|
||||
MHI_EE_WFW = 0x4, /* WIFI (WLAN) Firmware */
|
||||
MHI_EE_PT = 0x5, /* PassThrough, Non PCIe BOOT (PCIe is BIOS locked, not used for boot */
|
||||
MHI_EE_EDL = 0x6, /* PCIe enabled in PBL for emergency download (Non PCIe BOOT) */
|
||||
MHI_EE_FP = 0x7, /* FlashProg, Flash Programmer Environment */
|
||||
MHI_EE_BHIE = MHI_EE_FP,
|
||||
MHI_EE_UEFI = 0x8, /* UEFI */
|
||||
|
||||
MHI_EE_DISABLE_TRANSITION = 0x9,
|
||||
MHI_EE_MAX
|
||||
};
|
||||
|
||||
extern const char * const mhi_ee_str[MHI_EE_MAX];
|
||||
#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \
|
||||
"INVALID_EE" : mhi_ee_str[ee])
|
||||
|
||||
#define MHI_IN_PBL(ee) (ee == MHI_EE_PBL || ee == MHI_EE_PT || ee == MHI_EE_EDL)
|
||||
|
||||
enum MHI_ST_TRANSITION {
|
||||
MHI_ST_TRANSITION_PBL,
|
||||
MHI_ST_TRANSITION_READY,
|
||||
MHI_ST_TRANSITION_SBL,
|
||||
MHI_ST_TRANSITION_AMSS,
|
||||
MHI_ST_TRANSITION_FP,
|
||||
MHI_ST_TRANSITION_BHIE = MHI_ST_TRANSITION_FP,
|
||||
MHI_ST_TRANSITION_MAX,
|
||||
};
|
||||
|
||||
extern const char * const mhi_state_tran_str[MHI_ST_TRANSITION_MAX];
|
||||
#define TO_MHI_STATE_TRANS_STR(state) (((state) >= MHI_ST_TRANSITION_MAX) ? \
|
||||
"INVALID_STATE" : mhi_state_tran_str[state])
|
||||
|
||||
enum MHI_STATE {
|
||||
MHI_STATE_RESET = 0x0,
|
||||
MHI_STATE_READY = 0x1,
|
||||
MHI_STATE_M0 = 0x2,
|
||||
MHI_STATE_M1 = 0x3,
|
||||
MHI_STATE_M2 = 0x4,
|
||||
MHI_STATE_M3 = 0x5,
|
||||
MHI_STATE_D3 = 0x6,
|
||||
MHI_STATE_BHI = 0x7,
|
||||
MHI_STATE_SYS_ERR = 0xFF,
|
||||
MHI_STATE_MAX,
|
||||
};
|
||||
|
||||
extern const char * const mhi_state_str[MHI_STATE_MAX];
|
||||
#define TO_MHI_STATE_STR(state) ((state >= MHI_STATE_MAX || \
|
||||
!mhi_state_str[state]) ? \
|
||||
"INVALID_STATE" : mhi_state_str[state])
|
||||
|
||||
/* internal power states */
|
||||
enum MHI_PM_STATE {
|
||||
MHI_PM_DISABLE = BIT(0), /* MHI is not enabled */
|
||||
MHI_PM_POR = BIT(1), /* reset state */
|
||||
MHI_PM_M0 = BIT(2),
|
||||
MHI_PM_M1 = BIT(3),
|
||||
MHI_PM_M1_M2_TRANSITION = BIT(4), /* register access not allowed */
|
||||
MHI_PM_M2 = BIT(5),
|
||||
MHI_PM_M3_ENTER = BIT(6),
|
||||
MHI_PM_M3 = BIT(7),
|
||||
MHI_PM_M3_EXIT = BIT(8),
|
||||
MHI_PM_FW_DL_ERR = BIT(9), /* firmware download failure state */
|
||||
MHI_PM_SYS_ERR_DETECT = BIT(10),
|
||||
MHI_PM_SYS_ERR_PROCESS = BIT(11),
|
||||
MHI_PM_SHUTDOWN_PROCESS = BIT(12),
|
||||
MHI_PM_LD_ERR_FATAL_DETECT = BIT(13), /* link not accessible */
|
||||
};
|
||||
|
||||
#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \
|
||||
MHI_PM_M1 | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
|
||||
MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \
|
||||
MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR)))
|
||||
#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)
|
||||
#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT)
|
||||
#define MHI_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | MHI_PM_M1))
|
||||
#define MHI_WAKE_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | \
|
||||
MHI_PM_M1 | MHI_PM_M2))
|
||||
#define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \
|
||||
MHI_PM_IN_ERROR_STATE(pm_state))
|
||||
#define MHI_PM_IN_SUSPEND_STATE(pm_state) (pm_state & \
|
||||
(MHI_PM_M3_ENTER | MHI_PM_M3))
|
||||
|
||||
/* accepted buffer type for the channel */
|
||||
enum MHI_XFER_TYPE {
|
||||
MHI_XFER_BUFFER,
|
||||
MHI_XFER_SKB,
|
||||
MHI_XFER_SCLIST,
|
||||
MHI_XFER_NOP, /* CPU offload channel, host does not accept transfer */
|
||||
};
|
||||
|
||||
#define NR_OF_CMD_RINGS (1)
|
||||
#define CMD_EL_PER_RING (128)
|
||||
#define PRIMARY_CMD_RING (0)
|
||||
#define MHI_DEV_WAKE_DB (127)
|
||||
#define MHI_M2_DEBOUNCE_TMR_US (10000)
|
||||
#define MHI_MAX_MTU (0xffff)
|
||||
|
||||
enum MHI_ER_TYPE {
|
||||
MHI_ER_TYPE_INVALID = 0x0,
|
||||
MHI_ER_TYPE_VALID = 0x1,
|
||||
};
|
||||
|
||||
struct db_cfg {
|
||||
bool reset_req;
|
||||
bool db_mode;
|
||||
u32 pollcfg;
|
||||
enum MHI_BRSTMODE brstmode;
|
||||
dma_addr_t db_val;
|
||||
void (*process_db)(struct mhi_controller *mhi_cntrl,
|
||||
struct db_cfg *db_cfg, void __iomem *io_addr,
|
||||
dma_addr_t db_val);
|
||||
};
|
||||
|
||||
struct mhi_pm_transitions {
|
||||
enum MHI_PM_STATE from_state;
|
||||
u32 to_states;
|
||||
};
|
||||
|
||||
struct state_transition {
|
||||
struct list_head node;
|
||||
enum MHI_ST_TRANSITION state;
|
||||
};
|
||||
|
||||
/* Control Segment */
|
||||
struct mhi_ctrl_seg
|
||||
{
|
||||
struct __packed mhi_tre hw_in_chan_ring[NUM_MHI_IPA_IN_RING_ELEMENTS] __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16);
|
||||
struct __packed mhi_tre hw_out_chan_ring[NUM_MHI_IPA_OUT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16);
|
||||
struct __packed mhi_tre diag_in_chan_ring[NUM_MHI_IPA_OUT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16);
|
||||
struct __packed mhi_tre chan_ring[NUM_MHI_CHAN_RING_ELEMENTS*2*12] __aligned(NUM_MHI_CHAN_RING_ELEMENTS*16);
|
||||
//struct __packed mhi_tre event_ring[NUM_MHI_EVT_RINGS][NUM_MHI_EVT_RING_ELEMENTS] __aligned(NUM_MHI_EVT_RING_ELEMENTS*16);
|
||||
struct __packed mhi_tre event_ring_0[NUM_MHI_EVT_RING_ELEMENTS] __aligned(NUM_MHI_EVT_RING_ELEMENTS*16);
|
||||
struct __packed mhi_tre event_ring_1[NUM_MHI_IPA_OUT_EVT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_OUT_EVT_RING_ELEMENTS*16);
|
||||
struct __packed mhi_tre event_ring_2[NUM_MHI_IPA_IN_EVT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_IN_EVT_RING_ELEMENTS*16);
|
||||
struct __packed mhi_tre cmd_ring[NR_OF_CMD_RINGS][CMD_EL_PER_RING] __aligned(CMD_EL_PER_RING*16);
|
||||
|
||||
struct mhi_chan_ctxt chan_ctxt[NUM_MHI_XFER_RINGS] __aligned(128);
|
||||
struct mhi_event_ctxt er_ctxt[NUM_MHI_EVT_RINGS] __aligned(128);
|
||||
struct mhi_cmd_ctxt cmd_ctxt[NR_OF_CMD_RINGS] __aligned(128);
|
||||
} __aligned(4096);
|
||||
|
||||
struct mhi_ctxt {
|
||||
struct mhi_event_ctxt *er_ctxt;
|
||||
struct mhi_chan_ctxt *chan_ctxt;
|
||||
struct mhi_cmd_ctxt *cmd_ctxt;
|
||||
dma_addr_t er_ctxt_addr;
|
||||
dma_addr_t chan_ctxt_addr;
|
||||
dma_addr_t cmd_ctxt_addr;
|
||||
struct mhi_ctrl_seg *ctrl_seg;
|
||||
dma_addr_t ctrl_seg_addr;
|
||||
};
|
||||
|
||||
struct mhi_ring {
|
||||
dma_addr_t dma_handle;
|
||||
dma_addr_t iommu_base;
|
||||
u64 *ctxt_wp; /* point to ctxt wp */
|
||||
void *pre_aligned;
|
||||
void *base;
|
||||
void *rp;
|
||||
void *wp;
|
||||
size_t el_size;
|
||||
size_t len;
|
||||
size_t elements;
|
||||
size_t alloc_size;
|
||||
void __iomem *db_addr;
|
||||
};
|
||||
|
||||
struct mhi_cmd {
|
||||
struct mhi_ring ring;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct mhi_buf_info {
|
||||
dma_addr_t p_addr;
|
||||
void *v_addr;
|
||||
void *wp;
|
||||
size_t len;
|
||||
void *cb_buf;
|
||||
enum dma_data_direction dir;
|
||||
};
|
||||
|
||||
struct mhi_event {
|
||||
u32 er_index;
|
||||
u32 intmod;
|
||||
u32 msi;
|
||||
int chan; /* this event ring is dedicated to a channel */
|
||||
u32 priority;
|
||||
struct mhi_ring ring;
|
||||
struct db_cfg db_cfg;
|
||||
bool hw_ring;
|
||||
bool cl_manage;
|
||||
bool offload_ev; /* managed by a device driver */
|
||||
bool ctrl_ev;
|
||||
spinlock_t lock;
|
||||
struct mhi_chan *mhi_chan; /* dedicated to channel */
|
||||
struct tasklet_struct task;
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
};
|
||||
|
||||
struct mhi_chan {
|
||||
u32 chan;
|
||||
u32 ring;
|
||||
const char *name;
|
||||
/*
|
||||
* important, when consuming increment tre_ring first, when releasing
|
||||
* decrement buf_ring first. If tre_ring has space, buf_ring
|
||||
* guranteed to have space so we do not need to check both rings.
|
||||
*/
|
||||
struct mhi_ring buf_ring;
|
||||
struct mhi_ring tre_ring;
|
||||
u32 er_index;
|
||||
u32 intmod;
|
||||
u32 tiocm;
|
||||
u32 full;
|
||||
enum dma_data_direction dir;
|
||||
struct db_cfg db_cfg;
|
||||
enum MHI_EE ee;
|
||||
enum MHI_XFER_TYPE xfer_type;
|
||||
enum MHI_CH_STATE ch_state;
|
||||
enum MHI_EV_CCS ccs;
|
||||
bool lpm_notify;
|
||||
bool configured;
|
||||
bool offload_ch;
|
||||
bool pre_alloc;
|
||||
/* functions that generate the transfer ring elements */
|
||||
int (*gen_tre)(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan, void *buf, void *cb,
|
||||
size_t len, enum MHI_FLAGS flags);
|
||||
int (*queue_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS flags);
|
||||
/* xfer call back */
|
||||
struct mhi_device *mhi_dev;
|
||||
void (*xfer_cb)(struct mhi_device *mhi_dev, struct mhi_result *res);
|
||||
struct mutex mutex;
|
||||
struct completion completion;
|
||||
rwlock_t lock;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct mhi_bus {
|
||||
struct list_head controller_list;
|
||||
struct mutex lock;
|
||||
struct dentry *dentry;
|
||||
};
|
||||
|
||||
struct mhi_cntrl_data {
|
||||
struct mhi_ctxt mhi_ctxt;
|
||||
struct mhi_cmd mhi_cmd[NR_OF_CMD_RINGS];
|
||||
struct mhi_event mhi_event[NUM_MHI_EVT_RINGS];
|
||||
struct mhi_chan mhi_chan[MHI_MAX_CHANNELS];
|
||||
};
|
||||
|
||||
/* default MHI timeout */
|
||||
#define MHI_TIMEOUT_MS (3000)
|
||||
extern struct mhi_bus mhi_bus;
|
||||
|
||||
/* debug fs related functions */
|
||||
int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_trigger_reset(void *data, u64 val);
|
||||
|
||||
void mhi_deinit_debugfs(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_init_debugfs(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/* power management apis */
|
||||
enum MHI_PM_STATE __must_check mhi_tryset_pm_state(
|
||||
struct mhi_controller *mhi_cntrl,
|
||||
enum MHI_PM_STATE state);
|
||||
const char *to_mhi_pm_state_str(enum MHI_PM_STATE state);
|
||||
void mhi_reset_chan(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
enum MHI_EE mhi_get_exec_env(struct mhi_controller *mhi_cntrl);
|
||||
enum MHI_STATE mhi_get_m_state(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl,
|
||||
enum MHI_ST_TRANSITION state);
|
||||
void mhi_pm_st_worker(struct work_struct *work);
|
||||
void mhi_fw_load_worker(struct work_struct *work);
|
||||
void mhi_pm_m1_worker(struct work_struct *work);
|
||||
void mhi_pm_sys_err_worker(struct work_struct *work);
|
||||
int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_ctrl_ev_task(unsigned long data);
|
||||
int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason);
|
||||
|
||||
/* queue transfer buffer */
|
||||
int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
void *buf, void *cb, size_t buf_len, enum MHI_FLAGS flags);
|
||||
int mhi_queue_buf(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
int mhi_queue_skb(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
int mhi_queue_sclist(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
int mhi_queue_nop(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan,
|
||||
void *buf, size_t len, enum MHI_FLAGS mflags);
|
||||
|
||||
|
||||
/* register access methods */
|
||||
void mhi_db_brstmode(struct mhi_controller *mhi_cntrl, struct db_cfg *db_cfg,
|
||||
void __iomem *db_addr, dma_addr_t wp);
|
||||
void mhi_db_brstmode_disable(struct mhi_controller *mhi_cntrl,
|
||||
struct db_cfg *db_mode, void __iomem *db_addr,
|
||||
dma_addr_t wp);
|
||||
int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
|
||||
void __iomem *base, u32 offset, u32 *out);
|
||||
int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl,
|
||||
void __iomem *base, u32 offset, u32 mask,
|
||||
u32 shift, u32 *out);
|
||||
void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
||||
u32 offset, u32 val);
|
||||
void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base,
|
||||
u32 offset, u32 mask, u32 shift, u32 val);
|
||||
void mhi_ring_er_db(struct mhi_event *mhi_event);
|
||||
void mhi_write_db(struct mhi_controller *mhi_cntrl, void __iomem *db_addr,
|
||||
dma_addr_t wp);
|
||||
void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd);
|
||||
void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl, enum MHI_STATE state);
|
||||
|
||||
/* memory allocation methods */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 5,3,0 ))
|
||||
static inline void *dma_zalloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag)
|
||||
{
|
||||
void *ret = dma_alloc_coherent(dev, size, dma_handle,
|
||||
flag | __GFP_ZERO);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void *mhi_alloc_coherent(struct mhi_controller *mhi_cntrl,
|
||||
size_t size,
|
||||
dma_addr_t *dma_handle,
|
||||
gfp_t gfp)
|
||||
{
|
||||
void *buf = dma_zalloc_coherent(mhi_cntrl->dev, size, dma_handle, gfp);
|
||||
|
||||
MHI_LOG("size = %zd, dma_handle = %llx\n", size, (u64)*dma_handle);
|
||||
if (buf) {
|
||||
//if (*dma_handle < mhi_cntrl->iova_start || 0 == mhi_cntrl->iova_start)
|
||||
// mhi_cntrl->iova_start = (*dma_handle)&0xFFF0000000;
|
||||
//if ((*dma_handle + size) > mhi_cntrl->iova_stop || 0 == mhi_cntrl->iova_stop)
|
||||
// mhi_cntrl->iova_stop = ((*dma_handle + size)+0x0FFFFFFF)&0xFFF0000000;
|
||||
}
|
||||
if (buf)
|
||||
atomic_add(size, &mhi_cntrl->alloc_size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
static inline void mhi_free_coherent(struct mhi_controller *mhi_cntrl,
|
||||
size_t size,
|
||||
void *vaddr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
atomic_sub(size, &mhi_cntrl->alloc_size);
|
||||
dma_free_coherent(mhi_cntrl->dev, size, vaddr, dma_handle);
|
||||
}
|
||||
struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl);
|
||||
static inline void mhi_dealloc_device(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_device *mhi_dev)
|
||||
{
|
||||
kfree(mhi_dev);
|
||||
}
|
||||
int mhi_destroy_device(struct device *dev, void *data);
|
||||
void mhi_create_devices(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info **image_info, size_t alloc_size);
|
||||
void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *image_info);
|
||||
|
||||
/* initialization methods */
|
||||
int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
int mhi_init_mmio(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_dtr_init(void);
|
||||
|
||||
/* isr handlers */
|
||||
irqreturn_t mhi_msi_handlr(int irq_number, void *dev);
|
||||
irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev);
|
||||
irqreturn_t mhi_intvec_handlr(int irq_number, void *dev);
|
||||
void mhi_ev_task(unsigned long data);
|
||||
|
||||
#ifdef CONFIG_MHI_DEBUG
|
||||
|
||||
#define MHI_ASSERT(cond, msg) do { \
|
||||
if (cond) \
|
||||
panic(msg); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define MHI_ASSERT(cond, msg) do { \
|
||||
if (cond) { \
|
||||
MHI_ERR(msg); \
|
||||
WARN_ON(cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _MHI_INT_H */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,18 +0,0 @@
|
||||
#ifndef _FIBO_MHI_NETDEV_H
|
||||
#define _FIBO_MHI_NETDEV_H
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,15,0 ))
|
||||
static inline void *fibo_skb_put_data(struct sk_buff *skb, const void *data,
|
||||
unsigned int len)
|
||||
{
|
||||
void *tmp = skb_put(skb, len);
|
||||
|
||||
memcpy(tmp,data, len);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,785 +0,0 @@
|
||||
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/tty.h>
|
||||
#include "../core/mhi.h"
|
||||
|
||||
#define DEVICE_NAME "mhi"
|
||||
#define MHI_UCI_DRIVER_NAME "mhi_uci"
|
||||
|
||||
struct uci_chan {
|
||||
wait_queue_head_t wq;
|
||||
spinlock_t lock;
|
||||
struct list_head pending; /* user space waiting to read */
|
||||
struct uci_buf *cur_buf; /* current buffer user space reading */
|
||||
size_t rx_size;
|
||||
};
|
||||
|
||||
struct uci_buf {
|
||||
void *data;
|
||||
size_t len;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct uci_dev {
|
||||
struct list_head node;
|
||||
dev_t devt;
|
||||
struct device *dev;
|
||||
struct mhi_device *mhi_dev;
|
||||
const char *chan;
|
||||
struct mutex mutex; /* sync open and close */
|
||||
struct uci_chan ul_chan;
|
||||
struct uci_chan dl_chan;
|
||||
size_t mtu;
|
||||
int ref_count;
|
||||
bool enabled;
|
||||
bool disconnect;
|
||||
struct ktermios termios;
|
||||
int sigs;
|
||||
};
|
||||
|
||||
struct mhi_uci_drv {
|
||||
struct list_head head;
|
||||
struct mutex lock;
|
||||
struct class *class;
|
||||
int major;
|
||||
dev_t dev_t;
|
||||
};
|
||||
|
||||
enum MHI_DEBUG_LEVEL msg_lvl = MHI_MSG_LVL_ERROR;
|
||||
|
||||
typedef struct _QCQMI_HDR {
|
||||
u8 IFType;
|
||||
u16 Length;
|
||||
u8 CtlFlags; // reserved
|
||||
u8 QMIType;
|
||||
u8 ClientId;
|
||||
} __attribute__ ((packed)) *PQCQMI_HDR;
|
||||
|
||||
#define MSG_VERB(fmt, ...) do { \
|
||||
if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \
|
||||
pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define MSG_LOG(fmt, ...) do { \
|
||||
if (msg_lvl <= MHI_MSG_LVL_INFO) \
|
||||
pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define MSG_ERR(fmt, ...) do { \
|
||||
if (msg_lvl <= MHI_MSG_LVL_ERROR) \
|
||||
pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define MAX_UCI_DEVICES (64)
|
||||
#define QUEC_MHI_UCI_ALWAYS_OPEN //by now, sdx20 can not handle "start-reset-start" operation, so the simply solution is keep start state
|
||||
|
||||
static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES);
|
||||
static struct mhi_uci_drv mhi_uci_drv;
|
||||
|
||||
static int mhi_queue_inbound(struct uci_dev *uci_dev)
|
||||
{
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE);
|
||||
size_t mtu = uci_dev->mtu;
|
||||
void *buf;
|
||||
struct uci_buf *uci_buf;
|
||||
int ret = -EIO, i;
|
||||
|
||||
for (i = 0; i < nr_trbs; i++) {
|
||||
buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
uci_buf = buf + mtu;
|
||||
uci_buf->data = buf;
|
||||
|
||||
MSG_VERB("Allocated buf %d of %d size %zd\n", i, nr_trbs, mtu);
|
||||
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu,
|
||||
MHI_EOT);
|
||||
if (ret) {
|
||||
kfree(buf);
|
||||
MSG_ERR("Failed to queue buffer %d\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long mhi_uci_ioctl(struct file *file,
|
||||
unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
long ret = -ERESTARTSYS;
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
if (uci_dev->enabled) {
|
||||
switch (cmd) {
|
||||
case TCGETS:
|
||||
#ifndef TCGETS2
|
||||
ret = kernel_termios_to_user_termios((struct termios __user *)arg, &uci_dev->termios);
|
||||
#else
|
||||
ret = kernel_termios_to_user_termios_1((struct termios __user *)arg, &uci_dev->termios);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TCSETSF:
|
||||
case TCSETS:
|
||||
#ifndef TCGETS2
|
||||
ret = user_termios_to_kernel_termios(&uci_dev->termios, (struct termios __user *)arg);
|
||||
#else
|
||||
ret = user_termios_to_kernel_termios_1(&uci_dev->termios, (struct termios __user *)arg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case TIOCMSET:
|
||||
case TIOCMBIS:
|
||||
case TIOCMBIC:
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
ret = get_user(val, (uint32_t *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCMBIS:
|
||||
uci_dev->sigs |= val;
|
||||
break;
|
||||
case TIOCMBIC:
|
||||
uci_dev->sigs &= ~val;
|
||||
break;
|
||||
case TIOCMSET:
|
||||
uci_dev->sigs = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TIOCMGET:
|
||||
ret = put_user(uci_dev->sigs | TIOCM_RTS, (uint32_t *)arg);
|
||||
break;
|
||||
|
||||
case TCFLSH:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = mhi_ioctl(mhi_dev, cmd, arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_uci_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
uci_dev->ref_count--;
|
||||
if (!uci_dev->ref_count) {
|
||||
struct uci_buf *itr, *tmp;
|
||||
struct uci_chan *uci_chan;
|
||||
|
||||
MSG_LOG("Last client left, closing node\n");
|
||||
|
||||
if (uci_dev->enabled)
|
||||
mhi_unprepare_from_transfer(uci_dev->mhi_dev);
|
||||
|
||||
/* clean inbound channel */
|
||||
uci_chan = &uci_dev->dl_chan;
|
||||
list_for_each_entry_safe(itr, tmp, &uci_chan->pending, node) {
|
||||
list_del(&itr->node);
|
||||
kfree(itr->data);
|
||||
}
|
||||
if (uci_chan->cur_buf)
|
||||
kfree(uci_chan->cur_buf->data);
|
||||
|
||||
uci_chan->cur_buf = NULL;
|
||||
|
||||
if (!uci_dev->enabled) {
|
||||
MSG_LOG("Node is deleted, freeing dev node\n");
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
mutex_destroy(&uci_dev->mutex);
|
||||
clear_bit(MINOR(uci_dev->devt), uci_minors);
|
||||
kfree(uci_dev);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
MSG_LOG("exit: ref_count:%d\n", uci_dev->ref_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int mhi_uci_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
struct uci_chan *uci_chan;
|
||||
unsigned int mask = 0;
|
||||
|
||||
poll_wait(file, &uci_dev->dl_chan.wq, wait);
|
||||
poll_wait(file, &uci_dev->ul_chan.wq, wait);
|
||||
|
||||
uci_chan = &uci_dev->dl_chan;
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
mask = POLLERR;
|
||||
} else if (!list_empty(&uci_chan->pending) || uci_chan->cur_buf) {
|
||||
MSG_VERB("Client can read from node\n");
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
}
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
uci_chan = &uci_dev->ul_chan;
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
mask |= POLLERR;
|
||||
} else if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 0) {
|
||||
MSG_VERB("Client can write to node\n");
|
||||
mask |= POLLOUT | POLLWRNORM;
|
||||
}
|
||||
|
||||
if (uci_dev->disconnect)
|
||||
mask |= POLLHUP;
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
MSG_VERB("Client attempted to poll, returning mask 0x%x\n", mask);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static ssize_t mhi_uci_write(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t count,
|
||||
loff_t *offp)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
struct uci_chan *uci_chan = &uci_dev->ul_chan;
|
||||
size_t bytes_xfered = 0;
|
||||
int ret;
|
||||
|
||||
if (!buf || !count)
|
||||
return -EINVAL;
|
||||
|
||||
/* confirm channel is active */
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
MSG_VERB("Enter: to xfer:%zd bytes\n", count);
|
||||
|
||||
while (count) {
|
||||
size_t xfer_size;
|
||||
void *kbuf;
|
||||
enum MHI_FLAGS flags;
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) == 0 && (file->f_mode & FMODE_NDELAY))
|
||||
break;
|
||||
|
||||
/* wait for free descriptors */
|
||||
ret = wait_event_interruptible(uci_chan->wq,
|
||||
(!uci_dev->enabled) ||
|
||||
mhi_get_no_free_descriptors
|
||||
(mhi_dev, DMA_TO_DEVICE) > 0);
|
||||
|
||||
if (ret == -ERESTARTSYS) {
|
||||
MSG_LOG("Exit signal caught for node\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
xfer_size = min_t(size_t, count, uci_dev->mtu);
|
||||
kbuf = kmalloc(xfer_size, GFP_KERNEL);
|
||||
if (!kbuf) {
|
||||
MSG_ERR("Failed to allocate memory %zd\n", xfer_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = copy_from_user(kbuf, buf, xfer_size);
|
||||
if (unlikely(ret)) {
|
||||
kfree(kbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
flags = MHI_EOT;
|
||||
if (uci_dev->enabled)
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, kbuf,
|
||||
xfer_size, flags);
|
||||
else
|
||||
ret = -ERESTARTSYS;
|
||||
|
||||
if (ret) {
|
||||
kfree(kbuf);
|
||||
goto sys_interrupt;
|
||||
}
|
||||
|
||||
bytes_xfered += xfer_size;
|
||||
count -= xfer_size;
|
||||
buf += xfer_size;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
MSG_VERB("Exit: Number of bytes xferred:%zd\n", bytes_xfered);
|
||||
|
||||
return bytes_xfered;
|
||||
|
||||
sys_interrupt:
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t mhi_uci_read(struct file *file,
|
||||
char __user *buf,
|
||||
size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct uci_dev *uci_dev = file->private_data;
|
||||
struct mhi_device *mhi_dev = uci_dev->mhi_dev;
|
||||
struct uci_chan *uci_chan = &uci_dev->dl_chan;
|
||||
struct uci_buf *uci_buf;
|
||||
char *ptr;
|
||||
size_t to_copy;
|
||||
int ret = 0;
|
||||
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
MSG_VERB("Client provided buf len:%zd\n", count);
|
||||
|
||||
/* confirm channel is active */
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
/* No data available to read, wait */
|
||||
if (!uci_chan->cur_buf && list_empty(&uci_chan->pending)) {
|
||||
MSG_VERB("No data available to read waiting\n");
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
if (file->f_mode & FMODE_NDELAY)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = wait_event_interruptible(uci_chan->wq,
|
||||
(!uci_dev->enabled ||
|
||||
!list_empty(&uci_chan->pending)));
|
||||
if (ret == -ERESTARTSYS) {
|
||||
MSG_LOG("Exit signal caught for node\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
if (!uci_dev->enabled) {
|
||||
MSG_LOG("node is disabled\n");
|
||||
ret = -ERESTARTSYS;
|
||||
goto read_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* new read, get the next descriptor from the list */
|
||||
if (!uci_chan->cur_buf) {
|
||||
uci_buf = list_first_entry_or_null(&uci_chan->pending,
|
||||
struct uci_buf, node);
|
||||
if (unlikely(!uci_buf)) {
|
||||
ret = -EIO;
|
||||
goto read_error;
|
||||
}
|
||||
|
||||
list_del(&uci_buf->node);
|
||||
uci_chan->cur_buf = uci_buf;
|
||||
uci_chan->rx_size = uci_buf->len;
|
||||
MSG_VERB("Got pkt of size:%zd\n", uci_chan->rx_size);
|
||||
}
|
||||
|
||||
uci_buf = uci_chan->cur_buf;
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
/* Copy the buffer to user space */
|
||||
to_copy = min_t(size_t, count, uci_chan->rx_size);
|
||||
ptr = uci_buf->data + (uci_buf->len - uci_chan->rx_size);
|
||||
ret = copy_to_user(buf, ptr, to_copy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
MSG_VERB("Copied %zd of %zd bytes\n", to_copy, uci_chan->rx_size);
|
||||
uci_chan->rx_size -= to_copy;
|
||||
|
||||
/* we finished with this buffer, queue it back to hardware */
|
||||
if (!uci_chan->rx_size) {
|
||||
spin_lock_bh(&uci_chan->lock);
|
||||
uci_chan->cur_buf = NULL;
|
||||
|
||||
if (uci_dev->enabled)
|
||||
ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE,
|
||||
uci_buf->data, uci_dev->mtu,
|
||||
MHI_EOT);
|
||||
else
|
||||
ret = -ERESTARTSYS;
|
||||
|
||||
if (ret) {
|
||||
MSG_ERR("Failed to recycle element\n");
|
||||
kfree(uci_buf->data);
|
||||
goto read_error;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
}
|
||||
|
||||
MSG_VERB("Returning %zd bytes\n", to_copy);
|
||||
|
||||
return to_copy;
|
||||
|
||||
read_error:
|
||||
spin_unlock_bh(&uci_chan->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_uci_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct uci_dev *uci_dev;
|
||||
int ret = -EIO;
|
||||
struct uci_buf *buf_itr, *tmp;
|
||||
struct uci_chan *dl_chan;
|
||||
|
||||
mutex_lock(&mhi_uci_drv.lock);
|
||||
list_for_each_entry(uci_dev, &mhi_uci_drv.head, node) {
|
||||
if (uci_dev->devt == inode->i_rdev) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
|
||||
/* could not find a minor node */
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
if (!uci_dev->enabled) {
|
||||
MSG_ERR("Node exist, but not in active state!\n");
|
||||
goto error_open_chan;
|
||||
}
|
||||
|
||||
uci_dev->ref_count++;
|
||||
|
||||
MSG_LOG("Node open, ref counts %u\n", uci_dev->ref_count);
|
||||
|
||||
if (uci_dev->ref_count == 1) {
|
||||
MSG_LOG("Starting channel\n");
|
||||
ret = mhi_prepare_for_transfer(uci_dev->mhi_dev);
|
||||
if (ret) {
|
||||
MSG_ERR("Error starting transfer channels\n");
|
||||
uci_dev->ref_count--;
|
||||
goto error_open_chan;
|
||||
}
|
||||
|
||||
ret = mhi_queue_inbound(uci_dev);
|
||||
if (ret)
|
||||
goto error_rx_queue;
|
||||
|
||||
#ifdef QUEC_MHI_UCI_ALWAYS_OPEN
|
||||
uci_dev->ref_count++;
|
||||
if (uci_dev->mhi_dev->dl_chan_id == MHI_CLIENT_QMI_IN) {
|
||||
}
|
||||
if (uci_dev->mhi_dev->dl_chan_id == MHI_CLIENT_MBIM_IN) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
filp->private_data = uci_dev;
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
error_rx_queue:
|
||||
dl_chan = &uci_dev->dl_chan;
|
||||
mhi_unprepare_from_transfer(uci_dev->mhi_dev);
|
||||
list_for_each_entry_safe(buf_itr, tmp, &dl_chan->pending, node) {
|
||||
list_del(&buf_itr->node);
|
||||
kfree(buf_itr->data);
|
||||
}
|
||||
|
||||
error_open_chan:
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations mhidev_fops = {
|
||||
.open = mhi_uci_open,
|
||||
.release = mhi_uci_release,
|
||||
.read = mhi_uci_read,
|
||||
.write = mhi_uci_write,
|
||||
.poll = mhi_uci_poll,
|
||||
.unlocked_ioctl = mhi_uci_ioctl,
|
||||
};
|
||||
|
||||
static void mhi_uci_remove(struct mhi_device *mhi_dev)
|
||||
{
|
||||
struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev);
|
||||
|
||||
MSG_LOG("Enter\n");
|
||||
|
||||
/* disable the node */
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
spin_lock_irq(&uci_dev->dl_chan.lock);
|
||||
spin_lock_irq(&uci_dev->ul_chan.lock);
|
||||
uci_dev->enabled = false;
|
||||
uci_dev->disconnect = true;
|
||||
spin_unlock_irq(&uci_dev->ul_chan.lock);
|
||||
spin_unlock_irq(&uci_dev->dl_chan.lock);
|
||||
wake_up(&uci_dev->dl_chan.wq);
|
||||
wake_up(&uci_dev->ul_chan.wq);
|
||||
|
||||
/* delete the node to prevent new opens */
|
||||
device_destroy(mhi_uci_drv.class, uci_dev->devt);
|
||||
uci_dev->dev = NULL;
|
||||
mutex_lock(&mhi_uci_drv.lock);
|
||||
list_del(&uci_dev->node);
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
|
||||
#ifdef QUEC_MHI_UCI_ALWAYS_OPEN
|
||||
if (uci_dev->ref_count > 0)
|
||||
uci_dev->ref_count--;
|
||||
#endif
|
||||
|
||||
/* safe to free memory only if all file nodes are closed */
|
||||
if (!uci_dev->ref_count) {
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
mutex_destroy(&uci_dev->mutex);
|
||||
clear_bit(MINOR(uci_dev->devt), uci_minors);
|
||||
kfree(uci_dev);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
MSG_LOG("Exit\n");
|
||||
}
|
||||
|
||||
static int mhi_uci_probe(struct mhi_device *mhi_dev,
|
||||
const struct mhi_device_id *id)
|
||||
{
|
||||
struct uci_dev *uci_dev;
|
||||
int minor;
|
||||
int dir;
|
||||
|
||||
uci_dev = kzalloc(sizeof(*uci_dev), GFP_KERNEL);
|
||||
if (!uci_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&uci_dev->mutex);
|
||||
uci_dev->mhi_dev = mhi_dev;
|
||||
|
||||
minor = find_first_zero_bit(uci_minors, MAX_UCI_DEVICES);
|
||||
if (minor >= MAX_UCI_DEVICES) {
|
||||
kfree(uci_dev);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
mutex_lock(&uci_dev->mutex);
|
||||
mutex_lock(&mhi_uci_drv.lock);
|
||||
|
||||
uci_dev->devt = MKDEV(mhi_uci_drv.major, minor);
|
||||
|
||||
uci_dev->dev = device_create(mhi_uci_drv.class, &mhi_dev->dev,
|
||||
uci_dev->devt, uci_dev,
|
||||
DEVICE_NAME "_%s",
|
||||
mhi_dev->chan_name);
|
||||
|
||||
set_bit(minor, uci_minors);
|
||||
|
||||
for (dir = 0; dir < 2; dir++) {
|
||||
struct uci_chan *uci_chan = (dir) ?
|
||||
&uci_dev->ul_chan : &uci_dev->dl_chan;
|
||||
spin_lock_init(&uci_chan->lock);
|
||||
init_waitqueue_head(&uci_chan->wq);
|
||||
INIT_LIST_HEAD(&uci_chan->pending);
|
||||
};
|
||||
|
||||
uci_dev->termios = tty_std_termios;
|
||||
uci_dev->sigs = 0;
|
||||
|
||||
uci_dev->mtu = id->driver_data;
|
||||
mhi_device_set_devdata(mhi_dev, uci_dev);
|
||||
uci_dev->enabled = true;
|
||||
|
||||
list_add(&uci_dev->node, &mhi_uci_drv.head);
|
||||
mutex_unlock(&mhi_uci_drv.lock);
|
||||
mutex_unlock(&uci_dev->mutex);
|
||||
|
||||
MSG_LOG("channel:%s successfully probed\n", mhi_dev->chan_name);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static void mhi_ul_xfer_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev);
|
||||
struct uci_chan *uci_chan = &uci_dev->ul_chan;
|
||||
|
||||
MSG_VERB("status:%d xfer_len:%zu\n", mhi_result->transaction_status,
|
||||
mhi_result->bytes_xferd);
|
||||
|
||||
kfree(mhi_result->buf_addr);
|
||||
if (!mhi_result->transaction_status)
|
||||
wake_up(&uci_chan->wq);
|
||||
}
|
||||
|
||||
static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,
|
||||
struct mhi_result *mhi_result)
|
||||
{
|
||||
struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev);
|
||||
struct uci_chan *uci_chan = &uci_dev->dl_chan;
|
||||
unsigned long flags;
|
||||
struct uci_buf *buf;
|
||||
|
||||
MSG_VERB("chan:mhi_dev->dl_chan_id:%d, status:%d receive_len:%zu\n",
|
||||
mhi_dev->dl_chan_id, mhi_result->transaction_status, mhi_result->bytes_xferd);
|
||||
|
||||
if (mhi_result->transaction_status == -ENOTCONN) {
|
||||
kfree(mhi_result->buf_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&uci_chan->lock, flags);
|
||||
buf = mhi_result->buf_addr + uci_dev->mtu;
|
||||
if (buf->data != mhi_result->buf_addr) {
|
||||
MSG_LOG("%p, %p\n", buf->data, mhi_result->buf_addr);
|
||||
}
|
||||
buf->data = mhi_result->buf_addr;
|
||||
buf->len = mhi_result->bytes_xferd;
|
||||
|
||||
if (uci_dev->mhi_dev->dl_chan_id == MHI_CLIENT_QMI_IN) {
|
||||
PQCQMI_HDR pHdr = (PQCQMI_HDR) (buf->data);
|
||||
u16 qmiLength = (le16_to_cpu(pHdr->Length) + 1);
|
||||
|
||||
// open qmi chan, but not read data from the chan, will cause next error, donot know why by now, so it is not recomment to use uqmi&libqmi?
|
||||
// dmesg -c > /dev/null; echo 1 > /dev/mhi_QMI0; sleep 3; ./FIBO-CM -d /dev/mhi_QMI0 -v
|
||||
if (qmiLength != buf->len) {
|
||||
unsigned char *d = (unsigned char *) pHdr;
|
||||
MSG_ERR("bytes_xferd=%zd, qmiLength=%d %02x%02x%02x%02x - %02x%02x%02x%02x\n", buf->len, qmiLength,
|
||||
d[0],d[1],d[2],d[3],d[qmiLength+0],d[qmiLength+1],d[qmiLength+2],d[qmiLength+3]);
|
||||
if (buf->len > qmiLength)
|
||||
buf->len = qmiLength;
|
||||
}
|
||||
}
|
||||
|
||||
list_add_tail(&buf->node, &uci_chan->pending);
|
||||
spin_unlock_irqrestore(&uci_chan->lock, flags);
|
||||
|
||||
wake_up(&uci_chan->wq);
|
||||
}
|
||||
|
||||
#define DIAG_MAX_PCIE_PKT_SZ 2048 //define by module
|
||||
|
||||
/* .driver_data stores max mtu */
|
||||
static const struct mhi_device_id mhi_uci_match_table[] = {
|
||||
{ .chan = "LOOPBACK", .driver_data = 0x1000 },
|
||||
{ .chan = "SAHARA", .driver_data = 0x4000 },
|
||||
{ .chan = "EDL", .driver_data = 0x4000 },
|
||||
{ .chan = "DIAG", .driver_data = DIAG_MAX_PCIE_PKT_SZ },
|
||||
{ .chan = "EFS", .driver_data = 0x1000 },
|
||||
#ifdef CONFIG_MHI_NETDEV_MBIM
|
||||
{ .chan = "MBIM", .driver_data = 0x1000 },
|
||||
#else
|
||||
{ .chan = "QMI0", .driver_data = 0x1000 },
|
||||
{ .chan = "QMI1", .driver_data = 0x1000 },
|
||||
#endif
|
||||
{ .chan = "TF", .driver_data = 0x1000 },
|
||||
{ .chan = "BL", .driver_data = 0x1000 },
|
||||
{ .chan = "DUN", .driver_data = 0x1000 },
|
||||
{ .chan = "GNSS", .driver_data = 0x1000 },
|
||||
{ .chan = "AUDIO", .driver_data = 0x1000 },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct mhi_driver mhi_uci_driver = {
|
||||
.id_table = mhi_uci_match_table,
|
||||
.remove = mhi_uci_remove,
|
||||
.probe = mhi_uci_probe,
|
||||
.ul_xfer_cb = mhi_ul_xfer_cb,
|
||||
.dl_xfer_cb = mhi_dl_xfer_cb,
|
||||
.driver = {
|
||||
.name = MHI_UCI_DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
int mhi_device_uci_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_chrdev(0, MHI_UCI_DRIVER_NAME, &mhidev_fops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mhi_uci_drv.major = ret;
|
||||
mhi_uci_drv.class = class_create(THIS_MODULE, MHI_UCI_DRIVER_NAME);
|
||||
if (IS_ERR(mhi_uci_drv.class)) {
|
||||
unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_init(&mhi_uci_drv.lock);
|
||||
INIT_LIST_HEAD(&mhi_uci_drv.head);
|
||||
|
||||
ret = mhi_driver_register(&mhi_uci_driver);
|
||||
if (ret) {
|
||||
class_destroy(mhi_uci_drv.class);
|
||||
unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mhi_device_uci_exit(void)
|
||||
{
|
||||
mhi_driver_unregister(&mhi_uci_driver);
|
||||
class_destroy(mhi_uci_drv.class);
|
||||
unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME);
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015 OpenWrt-dist
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ipv6helper
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_LICENSE:=GPLv3
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_MAINTAINER:=LEAN
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ipv6helper
|
||||
SECTION:=ipv6
|
||||
TITLE:=IPv6 Helper and Dynamic Update he.net of ip
|
||||
PKGARCH:=all
|
||||
DEPENDS:=+luci-proto-ipv6 +wget +ip6tables +libip6tc +kmod-ipt-nat6 +odhcpd-ipv6only +odhcp6c +6in4
|
||||
endef
|
||||
|
||||
define Package/ipv6helper/description
|
||||
IPv6 Helper and Dynamic Update he.net of ip
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ipv6helper/postinst
|
||||
#!/bin/sh
|
||||
if [ -z "$${IPKG_INSTROOT}" ]; then
|
||||
chmod 755 /etc/hotplug.d/iface/60-6in4 >/dev/null 2>&1
|
||||
fi
|
||||
exit 0
|
||||
endef
|
||||
|
||||
define Package/ipv6helper/install
|
||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_BIN) ./files/root/etc/hotplug.d/iface/60-6in4 $(1)/etc/hotplug.d/iface/60-6in4
|
||||
endef
|
||||
|
||||
|
||||
$(eval $(call BuildPackage,ipv6helper))
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
if [ "$ACTION" != "ifup" ]; then
|
||||
exit
|
||||
fi
|
||||
config_load network
|
||||
config_get tunnelid $INTERFACE tunnelid
|
||||
config_get username $INTERFACE username
|
||||
config_get password $INTERFACE password
|
||||
if [ "$tunnelid" != "" ]; then
|
||||
wget -O - https://$username:$password@ipv4.tunnelbroker.net/nic/update?hostname=$tunnelid --no-check-certificate
|
||||
fi
|
||||
@@ -1,47 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=k3screenctrl
|
||||
PKG_VERSION:=0.10
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/updateing/k3screenctrl.git
|
||||
PKG_SOURCE_VERSION:=dd05ce9a5cb0cb6cebfc6b3b5823c7f6d75796ff
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_SOURCE_VERSION)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.xz
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
|
||||
PKG_MAINTAINER:=Hamster Tian <haotia@gmail.com>
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
TARGET_CFLAGS+= -D_GNU_SOURCE
|
||||
|
||||
define Package/k3screenctrl
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
DEPENDS:=@(TARGET_bcm53xx_generic_DEVICE_phicomm_k3||TARGET_DEVICE_bcm53xx_generic_DEVICE_phicomm_k3) +@KERNEL_DEVMEM
|
||||
TITLE:=LCD screen controller on PHICOMM K3
|
||||
URL:=https://github.com/updateing/k3-screen-ctrl
|
||||
endef
|
||||
|
||||
define Package/k3screenctrl/description
|
||||
K3 Screen Controller (k3screenctrl) is a program utilizing
|
||||
the LCD screen on PHICOMM K3 to display some stats.
|
||||
endef
|
||||
|
||||
define Package/k3screenctrl/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_DIR) $(1)/lib/k3screenctrl
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/k3screenctrl $(1)/usr/bin/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/k3screenctrl/wan.sh $(1)/lib/k3screenctrl/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/k3screenctrl/wifi.sh $(1)/lib/k3screenctrl/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/k3screenctrl/port.sh $(1)/lib/k3screenctrl/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/k3screenctrl/basic.sh $(1)/lib/k3screenctrl/
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib/k3screenctrl/host.sh $(1)/lib/k3screenctrl/
|
||||
|
||||
$(INSTALL_BIN) ./files/k3screenctrl.init $(1)/etc/init.d/k3screenctrl
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,k3screenctrl))
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
STOP=99
|
||||
|
||||
SCRIPTS_BASE=/lib/k3screenctrl/
|
||||
|
||||
start() {
|
||||
/usr/bin/k3screenctrl &
|
||||
}
|
||||
|
||||
stop() {
|
||||
killall k3screenctrl
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
diff -Nuar a/src/infocenter.c b/src/infocenter.c
|
||||
--- a/src/infocenter.c 2017-05-02 19:49:08.000000000 +0800
|
||||
+++ b/src/infocenter.c 2021-12-29 17:37:00.837529076 +0800
|
||||
@@ -116,9 +116,10 @@
|
||||
* be malformatted and the results are not reliable.
|
||||
*/
|
||||
const char *stopped_at = tokenize_and_store(out, '\n', stores, store_len);
|
||||
+ int ret = *stopped_at == 0 ? SUCCESS : FAILURE;
|
||||
+
|
||||
free((void *)out);
|
||||
-
|
||||
- return *stopped_at == 0 ? SUCCESS : FAILURE;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
BASIC_INFO g_basic_info;
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
#-- Copyright (C) 2018 dz <dingzhong110@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI Support for advancedsetting
|
||||
LUCI_DEPENDS:=
|
||||
PKG_VERSION:=1.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
@@ -1,14 +0,0 @@
|
||||
-- Copyright (C) 2018 dz <dingzhong110@gmail.com>
|
||||
|
||||
module("luci.controller.advancedsetting", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/advancedsetting") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
page = entry({"admin", "system", "advancedsetting"}, cbi("advancedsetting"), _("Advanced Setting"), 60)
|
||||
page.dependent = true
|
||||
page.acl_depends = { "luci-app-advancedsetting" }
|
||||
end
|
||||
@@ -1,87 +0,0 @@
|
||||
-- Copyright (C) 2018 dz <dingzhong110@gmail.com>
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
|
||||
m = Map("advancedsetting", translate("Advanced Setting"))
|
||||
m.description = translate("Direct editing of built-in Script Documents for various services, unless you know what you are doing, do not easily modify these configuration documents")
|
||||
|
||||
s = m:section(TypedSection, "advancedsetting")
|
||||
s.anonymous = true
|
||||
|
||||
--dnsmasq
|
||||
if nixio.fs.access("/etc/dnsmasq.conf") then
|
||||
s:tab("config1", translate("dnsmasq"), translate("This page is the document content for configuring /etc/dnsmasq.conf. Restart takes effect after application is saved"))
|
||||
conf = s:taboption("config1", Value, "editconf1", nil, translate("Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."))
|
||||
conf.template = "cbi/tvalue"
|
||||
conf.rows = 20
|
||||
conf.wrap = "off"
|
||||
|
||||
function conf.cfgvalue(self, section)
|
||||
return fs.readfile("/etc/dnsmasq.conf") or ""
|
||||
end
|
||||
|
||||
function conf.write(self, section, value)
|
||||
if value then
|
||||
value = value:gsub("\r\n?", "\n")
|
||||
fs.writefile("/tmp/dnsmasq.conf", value)
|
||||
if (luci.sys.call("cmp -s /tmp/dnsmasq.conf /etc/dnsmasq.conf") == 1) then
|
||||
fs.writefile("/etc/dnsmasq.conf", value)
|
||||
luci.sys.call("/etc/init.d/dnsmasq restart >/dev/null")
|
||||
end
|
||||
fs.remove("/tmp/dnsmasq.conf")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--network
|
||||
if nixio.fs.access("/etc/config/network") then
|
||||
s:tab("config2", translate("network"), translate("This page is the document content for configuring /etc/config/network. Restart takes effect after application is saved"))
|
||||
conf = s:taboption("config2", Value, "editconf2", nil, translate("Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."))
|
||||
conf.template = "cbi/tvalue"
|
||||
conf.rows = 20
|
||||
conf.wrap = "off"
|
||||
|
||||
function conf.cfgvalue(self, section)
|
||||
return fs.readfile("/etc/config/network") or ""
|
||||
end
|
||||
|
||||
function conf.write(self, section, value)
|
||||
if value then
|
||||
value = value:gsub("\r\n?", "\n")
|
||||
fs.writefile("/tmp/netwok", value)
|
||||
if (luci.sys.call("cmp -s /tmp/network /etc/config/network") == 1) then
|
||||
fs.writefile("/etc/config/network", value)
|
||||
luci.sys.call("/etc/init.d/network restart >/dev/null")
|
||||
end
|
||||
fs.remove("/tmp/network")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--hosts
|
||||
if nixio.fs.access("/etc/hosts") then
|
||||
s:tab("config3", translate("hosts"), translate("This page is the document content for configuring /etc/hosts. Restart takes effect after application is saved"))
|
||||
conf = s:taboption("config3", Value, "editconf3", nil, translate("Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."))
|
||||
conf.template = "cbi/tvalue"
|
||||
conf.rows = 20
|
||||
conf.wrap = "off"
|
||||
|
||||
function conf.cfgvalue(self, section)
|
||||
return fs.readfile("/etc/hosts") or ""
|
||||
end
|
||||
|
||||
function conf.write(self, section, value)
|
||||
if value then
|
||||
value = value:gsub("\r\n?", "\n")
|
||||
fs.writefile("/tmp/etc/hosts", value)
|
||||
if (luci.sys.call("cmp -s /tmp/etc/hosts /etc/hosts") == 1) then
|
||||
fs.writefile("/etc/hosts", value)
|
||||
luci.sys.call("/etc/init.d/dnsmasq restart >/dev/null")
|
||||
end
|
||||
fs.remove("/tmp/etc/hosts")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
||||
@@ -1 +0,0 @@
|
||||
zh_Hans
|
||||
@@ -1,21 +0,0 @@
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
||||
msgid "Advanced Setting"
|
||||
msgstr "高级设置"
|
||||
|
||||
msgid "Direct editing of built-in Script Documents for various services, unless you know what you are doing, do not easily modify these configuration documents"
|
||||
msgstr "各类服务内置脚本文档的直接编辑,除非你知道自己在干什么,否则请不要轻易修改这些配置文档"
|
||||
|
||||
msgid "This page is the document content for configuring /etc/dnsmasq.conf. Restart takes effect after application is saved"
|
||||
msgstr "本页是配置/etc/dnsmasq.conf的文档内容。应用保存后重启生效"
|
||||
|
||||
msgid "Each line of the opening numeric symbol (#) or semicolon (;) is considered a comment; delete (;) and enable the specified option."
|
||||
msgstr "开头的数字符号(#)或分号的每一行(;)被视为注释;删除(;)启用指定选项。"
|
||||
|
||||
msgid "This page is the document content for configuring /etc/config/network. Restart takes effect after application is saved"
|
||||
msgstr "本页是配置/etc/config/network的文档内容。"
|
||||
|
||||
msgid "This page is the document content for configuring /etc/hosts. Restart takes effect after application is saved"
|
||||
msgstr "本页是配置/etc/hosts的文档内容。"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
config advancedsetting
|
||||
Loaded 100 of 2803 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user