blob: e9412b28feb38bcd55002d4d8a3a9d3bb3b1448e [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#!/bin/sh
2
3[ -n "$INCLUDE_ONLY" ] || {
4 . /lib/functions.sh
5 . ../netifd-proto.sh
6 init_proto "$@"
7}
8
9proto_ncm_init_config() {
10 no_device=1
11 available=1
12 proto_config_add_string "device:device"
13 proto_config_add_string ifname
14 proto_config_add_string apn
15 proto_config_add_string auth
16 proto_config_add_string username
17 proto_config_add_string password
18 proto_config_add_string pincode
19 proto_config_add_string delay
20 proto_config_add_string mode
21 proto_config_add_string pdptype
22 proto_config_add_boolean sourcefilter
23 proto_config_add_boolean delegate
24 proto_config_add_int profile
25 proto_config_add_defaults
26}
27
28proto_ncm_setup() {
29 local interface="$1"
30
31 local manufacturer initialize setmode connect finalize devname devpath ifpath
32
33 local device ifname apn auth username password pincode delay mode pdptype profile $PROTO_DEFAULT_OPTIONS
34 json_get_vars device ifname apn auth username password pincode delay mode pdptype sourcefilter delegate profile $PROTO_DEFAULT_OPTIONS
35
36 local context_type
37
38 [ "$metric" = "" ] && metric="0"
39
40 [ -n "$profile" ] || profile=1
41
42 pdptype=$(echo "$pdptype" | awk '{print toupper($0)}')
43 [ "$pdptype" = "IP" -o "$pdptype" = "IPV6" -o "$pdptype" = "IPV4V6" ] || pdptype="IP"
44
45 [ "$pdptype" = "IPV4V6" ] && context_type=3
46 [ -z "$context_type" -a "$pdptype" = "IPV6" ] && context_type=2
47 [ -n "$context_type" ] || context_type=1
48
49 [ -n "$ctl_device" ] && device=$ctl_device
50
51 [ -n "$device" ] || {
52 echo "No control device specified"
53 proto_notify_error "$interface" NO_DEVICE
54 proto_set_available "$interface" 0
55 return 1
56 }
57
58 device="$(readlink -f $device)"
59 [ -e "$device" ] || {
60 echo "Control device not valid"
61 proto_set_available "$interface" 0
62 return 1
63 }
64
65 [ -z "$ifname" ] && {
66 devname="$(basename "$device")"
67 case "$devname" in
68 'ttyACM'*)
69 devpath="$(readlink -f /sys/class/tty/$devname/device)"
70 ifpath="$devpath/../*/net"
71 ;;
72 'tty'*)
73 devpath="$(readlink -f /sys/class/tty/$devname/device)"
74 ifpath="$devpath/../../*/net"
75 ;;
76 *)
77 devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
78 ifpath="$devpath/net"
79 ;;
80 esac
81 ifname="$(ls $(ls -1 -d $ifpath | head -n 1))"
82 }
83
84 [ -n "$ifname" ] || {
85 echo "The interface could not be found."
86 proto_notify_error "$interface" NO_IFACE
87 proto_set_available "$interface" 0
88 return 1
89 }
90
91 start=$(date +%s)
92 while true; do
93 manufacturer=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | awk 'NF && $0 !~ /AT\+CGMI/ { sub(/\+CGMI: /,""); print tolower($1); exit; }')
94 [ "$manufacturer" = "error" ] && {
95 manufacturer=""
96 }
97 [ -n "$manufacturer" ] && {
98 break
99 }
100 [ -z "$delay" ] && {
101 break
102 }
103 sleep 1
104 elapsed=$(($(date +%s) - start))
105 [ "$elapsed" -gt "$delay" ] && {
106 break
107 }
108 done
109 [ -z "$manufacturer" ] && {
110 echo "Failed to get modem information"
111 proto_notify_error "$interface" GETINFO_FAILED
112 return 1
113 }
114
115 json_load "$(cat /etc/gcom/ncm.json)"
116 json_select "$manufacturer"
117 [ $? -ne 0 ] && {
118 echo "Unsupported modem"
119 proto_notify_error "$interface" UNSUPPORTED_MODEM
120 proto_set_available "$interface" 0
121 return 1
122 }
123
124 json_get_values initialize initialize
125 for i in $initialize; do
126 eval COMMAND="$i" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
127 echo "Failed to initialize modem"
128 proto_notify_error "$interface" INITIALIZE_FAILED
129 return 1
130 }
131 done
132
133 [ -n "$pincode" ] && {
134 PINCODE="$pincode" gcom -d "$device" -s /etc/gcom/setpin.gcom || {
135 echo "Unable to verify PIN"
136 proto_notify_error "$interface" PIN_FAILED
137 proto_block_restart "$interface"
138 return 1
139 }
140 }
141
142 json_get_values configure configure
143 echo "Configuring modem"
144 for i in $configure; do
145 eval COMMAND="$i" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
146 echo "Failed to configure modem"
147 proto_notify_error "$interface" CONFIGURE_FAILED
148 return 1
149 }
150 done
151
152 [ -n "$mode" ] && {
153 json_select modes
154 json_get_var setmode "$mode"
155 [ -n "$setmode" ] && {
156 echo "Setting mode"
157 eval COMMAND="$setmode" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
158 echo "Failed to set operating mode"
159 proto_notify_error "$interface" SETMODE_FAILED
160 return 1
161 }
162 }
163 json_select ..
164 }
165
166 echo "Starting network $interface"
167 json_get_vars connect
168 [ -n "$connect" ] && {
169 echo "Connecting modem"
170 eval COMMAND="$connect" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
171 echo "Failed to connect"
172 proto_notify_error "$interface" CONNECT_FAILED
173 return 1
174 }
175 }
176
177 json_get_vars finalize
178
179 echo "Setting up $ifname"
180 proto_init_update "$ifname" 1
181 proto_add_data
182 json_add_string "manufacturer" "$manufacturer"
183 proto_close_data
184 proto_send_update "$interface"
185
186 local zone="$(fw3 -q network "$interface" 2>/dev/null)"
187
188 [ "$pdptype" = "IP" -o "$pdptype" = "IPV4V6" ] && {
189 json_init
190 json_add_string name "${interface}_4"
191 json_add_string ifname "@$interface"
192 json_add_string proto "dhcp"
193 proto_add_dynamic_defaults
194 [ -n "$zone" ] && {
195 json_add_string zone "$zone"
196 }
197 json_close_object
198 ubus call network add_dynamic "$(json_dump)"
199 }
200
201 [ "$pdptype" = "IPV6" -o "$pdptype" = "IPV4V6" ] && {
202 json_init
203 json_add_string name "${interface}_6"
204 json_add_string ifname "@$interface"
205 json_add_string proto "dhcpv6"
206 json_add_string extendprefix 1
207 [ "$delegate" = "0" ] && json_add_boolean delegate "0"
208 [ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
209 proto_add_dynamic_defaults
210 [ -n "$zone" ] && {
211 json_add_string zone "$zone"
212 }
213 json_close_object
214 ubus call network add_dynamic "$(json_dump)"
215 }
216
217 [ -n "$finalize" ] && {
218 eval COMMAND="$finalize" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
219 echo "Failed to configure modem"
220 proto_notify_error "$interface" FINALIZE_FAILED
221 return 1
222 }
223 }
224}
225
226proto_ncm_teardown() {
227 local interface="$1"
228
229 local manufacturer disconnect
230
231 local device profile
232 json_get_vars device profile
233
234 [ -n "$ctl_device" ] && device=$ctl_device
235
236 [ -n "$device" ] || {
237 echo "No control device specified"
238 proto_notify_error "$interface" NO_DEVICE
239 proto_set_available "$interface" 0
240 return 1
241 }
242
243 device="$(readlink -f $device)"
244 [ -e "$device" ] || {
245 echo "Control device not valid"
246 proto_set_available "$interface" 0
247 return 1
248 }
249
250 [ -n "$profile" ] || profile=1
251
252 echo "Stopping network $interface"
253
254 json_load "$(ubus call network.interface.$interface status)"
255 json_select data
256 json_get_vars manufacturer
257 [ $? -ne 0 -o -z "$manufacturer" ] && {
258 # Fallback to direct detect, for proper handle device replug.
259 manufacturer=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | awk 'NF && $0 !~ /AT\+CGMI/ { sub(/\+CGMI: /,""); print tolower($1); exit; }')
260 [ $? -ne 0 -o -z "$manufacturer" ] && {
261 echo "Failed to get modem information"
262 proto_notify_error "$interface" GETINFO_FAILED
263 return 1
264 }
265 json_add_string "manufacturer" "$manufacturer"
266 }
267
268 json_load "$(cat /etc/gcom/ncm.json)"
269 json_select "$manufacturer" || {
270 echo "Unsupported modem"
271 proto_notify_error "$interface" UNSUPPORTED_MODEM
272 return 1
273 }
274
275 json_get_vars disconnect
276 [ -n "$disconnect" ] && {
277 eval COMMAND="$disconnect" gcom -d "$device" -s /etc/gcom/runcommand.gcom || {
278 echo "Failed to disconnect"
279 proto_notify_error "$interface" DISCONNECT_FAILED
280 return 1
281 }
282 }
283
284 proto_init_update "*" 0
285 proto_send_update "$interface"
286}
287[ -n "$INCLUDE_ONLY" ] || {
288 add_protocol ncm
289}