xref: /OK3568_Linux_fs/app/forlinx/quectelCM/qmap_bridge_mode.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2   @file    qmap_bridge_mode.c
3   @brief   Connectivity bridge manager.
4 
5   DESCRIPTION
6   Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules.
7 
8   INITIALIZATION AND SEQUENCING REQUIREMENTS
9   None.
10 
11   ---------------------------------------------------------------------------
12   Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd.  All Rights Reserved.
13   Quectel Wireless Solution Proprietary and Confidential.
14   ---------------------------------------------------------------------------
15 ******************************************************************************/
16 #include "QMIThread.h"
17 
ql_fread(const char * filename,void * buf,size_t size)18 static size_t ql_fread(const char *filename, void *buf, size_t size) {
19     FILE *fp = fopen(filename , "r");
20     size_t n = 0;
21 
22     memset(buf, 0x00, size);
23 
24     if (fp) {
25         n = fread(buf, 1, size, fp);
26         if (n <= 0 || n == size) {
27             dbg_time("warnning: fail to fread(%s), fread=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno));
28         }
29         fclose(fp);
30     }
31 
32     return n > 0 ? n : 0;
33 }
34 
ql_fwrite(const char * filename,const void * buf,size_t size)35 static size_t ql_fwrite(const char *filename, const void *buf, size_t size) {
36     FILE *fp = fopen(filename , "w");
37     size_t n = 0;
38 
39     if (fp) {
40         n = fwrite(buf, 1, size, fp);
41         if (n != size) {
42             dbg_time("warnning: fail to fwrite(%s), fwrite=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno));
43         }
44         fclose(fp);
45     }
46 
47     return n > 0 ? n : 0;
48 }
49 
ql_bridge_mode_detect(PROFILE_T * profile)50 int ql_bridge_mode_detect(PROFILE_T *profile) {
51     const char *ifname = profile->qmapnet_adapter[0] ? profile->qmapnet_adapter : profile->usbnet_adapter;
52     const char *driver;
53     char bridge_mode[128];
54     char bridge_ipv4[128];
55     char ipv4[128];
56     char buf[64];
57     size_t n;
58     int in_bridge = 0;
59 
60     driver = profile->driver_name;
61     snprintf(bridge_mode, sizeof(bridge_mode), "/sys/class/net/%s/bridge_mode", ifname);
62     snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/class/net/%s/bridge_ipv4", ifname);
63 
64     if (access(bridge_ipv4, R_OK)) {
65         if (errno != ENOENT) {
66             dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno));
67             return 0;
68         }
69 
70         snprintf(bridge_mode, sizeof(bridge_mode), "/sys/module/%s/parameters/bridge_mode", driver);
71         snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/module/%s/parameters/bridge_ipv4", driver);
72 
73         if (access(bridge_mode, R_OK)) {
74             if (errno != ENOENT) {
75                 dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno));
76             }
77             return 0;
78         }
79     }
80 
81     n = ql_fread(bridge_mode, buf, sizeof(buf));
82     if (n > 0) {
83         in_bridge = (buf[0] != '0');
84     }
85     if (!in_bridge)
86         return 0;
87 
88     memset(ipv4, 0, sizeof(ipv4));
89 
90     if (strstr(bridge_ipv4, "/sys/class/net/") || profile->qmap_mode == 0 || profile->qmap_mode == 1) {
91         snprintf(ipv4, sizeof(ipv4), "0x%x", profile->ipv4.Address);
92         dbg_time("echo '%s' > %s", ipv4, bridge_ipv4);
93         ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4));
94     }
95     else {
96         snprintf(ipv4, sizeof(ipv4), "0x%x:%d", profile->ipv4.Address, profile->muxid);
97         dbg_time("echo '%s' > %s", ipv4, bridge_ipv4);
98         ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4));
99     }
100 
101     return in_bridge;
102 }
103 
ql_enable_qmi_wwan_rawip_mode(PROFILE_T * profile)104 int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile) {
105     char filename[256];
106     char buf[4];
107     size_t n;
108     FILE *fp;
109 
110     if (!qmidev_is_qmiwwan(profile->qmichannel))
111         return 0;
112 
113     snprintf(filename, sizeof(filename), "/sys/class/net/%s/qmi/rawip", profile->usbnet_adapter);
114     n = ql_fread(filename, buf, sizeof(buf));
115 
116     if (n == 0)
117         return 0;
118 
119     if (buf[0] == '1' || buf[0] == 'Y')
120         return 0;
121 
122     fp = fopen(filename , "w");
123     if (fp == NULL) {
124         dbg_time("Fail to fopen(%s, \"w\"), errno: %d (%s)", filename, errno, strerror(errno));
125         return 1;
126     }
127 
128     buf[0] = 'Y';
129     n = fwrite(buf, 1, 1, fp);
130     if (n != 1) {
131         dbg_time("Fail to fwrite(%s), errno: %d (%s)", filename, errno, strerror(errno));
132         fclose(fp);
133         return 1;
134     }
135     fclose(fp);
136 
137     return 0;
138 }
139 
ql_driver_type_detect(PROFILE_T * profile)140 int ql_driver_type_detect(PROFILE_T *profile) {
141     if (qmidev_is_gobinet(profile->qmichannel)) {
142         profile->qmi_ops = &gobi_qmidev_ops;
143     }
144     else {
145         profile->qmi_ops = &qmiwwan_qmidev_ops;
146     }
147     qmidev_send = profile->qmi_ops->send;
148 
149     return 0;
150 }
151 
ql_set_driver_bridge_mode(PROFILE_T * profile)152 void ql_set_driver_bridge_mode(PROFILE_T *profile) {
153     char enable[16];
154     char filename[256];
155 
156     if(profile->qmap_mode)
157         snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->qmapnet_adapter);
158     else
159         snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->usbnet_adapter);
160     snprintf(enable, sizeof(enable), "%02d\n", profile->enable_bridge);
161     ql_fwrite(filename, enable, sizeof(enable));
162 }
163 
ql_qmi_qmap_mode_detect(PROFILE_T * profile)164 static int ql_qmi_qmap_mode_detect(PROFILE_T *profile) {
165     char buf[128];
166     int n;
167     struct {
168         char filename[255 * 2];
169         char linkname[255 * 2];
170     } *pl;
171 
172     pl = (typeof(pl)) malloc(sizeof(*pl));
173 
174     snprintf(pl->linkname, sizeof(pl->linkname), "/sys/class/net/%s/device/driver", profile->usbnet_adapter);
175     n = readlink(pl->linkname, pl->filename, sizeof(pl->filename));
176     pl->filename[n] = '\0';
177     while (pl->filename[n] != '/')
178         n--;
179     strncpy(profile->driver_name, &pl->filename[n+1], sizeof(profile->driver_name));
180 
181     ql_get_driver_rmnet_info(profile, &profile->rmnet_info);
182     if (profile->rmnet_info.size) {
183         profile->qmap_mode = profile->rmnet_info.qmap_mode;
184         if (profile->qmap_mode) {
185             int offset_id = (profile->muxid == 0)? profile->pdp - 1 : profile->muxid - 0x81;
186 
187             if (profile->qmap_mode == 1)
188                 offset_id = 0;
189             profile->muxid = profile->rmnet_info.mux_id[offset_id];
190             strncpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id], sizeof(profile->qmapnet_adapter));
191             profile->qmap_size = profile->rmnet_info.rx_urb_size;
192             profile->qmap_version = profile->rmnet_info.qmap_version;
193         }
194 
195         goto _out;
196     }
197 
198     snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_mode", profile->usbnet_adapter);
199     if (access(pl->filename, R_OK)) {
200         if (errno != ENOENT) {
201             dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno));
202             goto _out;
203         }
204 
205         snprintf(pl->filename, sizeof(pl->filename), "/sys/module/%s/parameters/qmap_mode", profile->driver_name);
206         if (access(pl->filename, R_OK)) {
207             if (errno != ENOENT) {
208                 dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno));
209                 goto _out;
210             }
211 
212             snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/device/driver/module/parameters/qmap_mode", profile->usbnet_adapter);
213             if (access(pl->filename, R_OK)) {
214                 if (errno != ENOENT) {
215                     dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno));
216                     goto _out;
217                 }
218             }
219         }
220     }
221 
222     if (!access(pl->filename, R_OK)) {
223         n = ql_fread(pl->filename, buf, sizeof(buf));
224         if (n > 0) {
225             profile->qmap_mode = atoi(buf);
226 
227             if (profile->qmap_mode > 1) {
228                 if(!profile->muxid)
229                 	profile->muxid = profile->pdp + 0x80; //muxis is 0x8X for PDN-X
230                 snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter),
231                     "%.16s.%d", profile->usbnet_adapter, profile->muxid - 0x80);
232            } if (profile->qmap_mode == 1) {
233                 profile->muxid = 0x81;
234                 strncpy(profile->qmapnet_adapter, profile->usbnet_adapter, sizeof(profile->qmapnet_adapter));
235            }
236         }
237     }
238     else if (qmidev_is_qmiwwan(profile->qmichannel)) {
239         snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/qmimux%d", profile->pdp - 1);
240         if (access(pl->filename, R_OK)) {
241             if (errno != ENOENT) {
242                 dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno));
243             }
244             goto _out;
245         }
246 
247         //upstream Kernel Style QMAP qmi_wwan.c
248         snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter);
249         n = ql_fread(pl->filename, buf, sizeof(buf));
250         if (n >= 5) {
251             dbg_time("If use QMAP by /sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter);
252             dbg_time("File:%s Line:%d Please make sure add next patch to qmi_wwan.c", __func__, __LINE__);
253             /*
254             diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
255             index 74bebbd..db8a777 100644
256             --- a/drivers/net/usb/qmi_wwan.c
257             +++ b/drivers/net/usb/qmi_wwan.c
258             @@ -379,6 +379,24 @@ static ssize_t add_mux_store(struct device *d,  struct device_attribute *attr, c
259                 if (!ret) {
260                         info->flags |= QMI_WWAN_FLAG_MUX;
261                         ret = len;
262             +#if 1 //Add by Quectel
263             +               if (le16_to_cpu(dev->udev->descriptor.idVendor) == 0x2c7c) {
264             +                       int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct);
265             +
266             +                       if (idProduct == 0x0121 || idProduct == 0x0125 || idProduct == 0x0435) //MDM9x07
267             +                               dev->rx_urb_size = 4*1024;
268             +                       else if (idProduct == 0x0306) //MDM9x40
269             +                               dev->rx_urb_size = 16*1024;
270             +                       else if (idProduct == 0x0512) //SDX20
271             +                               dev->rx_urb_size = 32*1024;
272             +                       else if (idProduct == 0x0620) //SDX24
273             +                               dev->rx_urb_size = 32*1024;
274             +                       else if (idProduct == 0x0800) //SDX55
275             +                               dev->rx_urb_size = 32*1024;
276             +                       else
277             +                               dev->rx_urb_size = 32*1024;
278             +               }
279             +#endif
280                 }
281             err:
282                 rtnl_unlock();
283             */
284             profile->qmap_mode = n/5; //0x11\n0x22\n0x33\n
285             if (profile->qmap_mode > 1) {
286                 //PDN-X map to qmimux-X
287                 if(!profile->muxid) {
288                 	profile->muxid = (buf[5*(profile->pdp - 1) + 2] - '0')*16 + (buf[5*(profile->pdp - 1) + 3] - '0');
289                     snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->pdp - 1);
290                 } else {
291 					profile->muxid = (buf[5*(profile->muxid - 0x81) + 2] - '0')*16 + (buf[5*(profile->muxid - 0x81) + 3] - '0');
292                     snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->muxid - 0x81);
293                 }
294             } else if (profile->qmap_mode == 1) {
295                 profile->muxid = (buf[5*0 + 2] - '0')*16 + (buf[5*0 + 3] - '0');
296                 snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter),
297                     "qmimux%d", 0);
298             }
299         }
300     }
301 
302 _out:
303     if (profile->qmap_mode) {
304         if (profile->qmap_size == 0) {
305             profile->qmap_size = 16*1024;
306             snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_size", profile->usbnet_adapter);
307             if (!access(pl->filename, R_OK)) {
308                 size_t n;
309                 char buf[32];
310                 n = ql_fread(pl->filename, buf, sizeof(buf));
311                 if (n > 0) {
312                     profile->qmap_size = atoi(buf);
313                 }
314             }
315         }
316 
317         if (profile->qmap_version == 0) {
318             profile->qmap_version = WDA_DL_DATA_AGG_QMAP_ENABLED;
319         }
320 
321         dbg_time("qmap_mode = %d, qmap_version = %d, qmap_size = %d, muxid = 0x%02x, qmap_netcard = %s",
322             profile->qmap_mode, profile->qmap_version, profile->qmap_size, profile->muxid, profile->qmapnet_adapter);
323     }
324     ql_set_driver_bridge_mode(profile);
325     free(pl);
326 
327     return 0;
328 }
329 
ql_mbim_usb_vlan_mode_detect(PROFILE_T * profile)330 static int ql_mbim_usb_vlan_mode_detect(PROFILE_T *profile) {
331     char tmp[128];
332 
333     snprintf(tmp, sizeof(tmp), "/sys/class/net/%s.%d", profile->usbnet_adapter, profile->pdp);
334     if (!access(tmp, F_OK)) {
335         profile->qmap_mode = 4;
336         profile->muxid = profile->pdp;
337         strncpy(profile->qmapnet_adapter, &tmp[strlen("/sys/class/net/")], sizeof(profile->qmapnet_adapter));
338 
339         dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s",
340             profile->qmap_mode, profile->muxid, profile->qmapnet_adapter);
341     }
342 
343     return 0;
344 }
345 
ql_mbim_mhi_qmap_mode_detect(PROFILE_T * profile)346 static int ql_mbim_mhi_qmap_mode_detect(PROFILE_T *profile) {
347     ql_get_driver_rmnet_info(profile, &profile->rmnet_info);
348     if (profile->rmnet_info.size) {
349         profile->qmap_mode = profile->rmnet_info.qmap_mode;
350         if (profile->qmap_mode) {
351             int offset_id = profile->pdp - 1;
352 
353             if (profile->qmap_mode == 1)
354                 offset_id = 0;
355             profile->muxid = offset_id;
356             strcpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id]);
357             profile->qmap_size = profile->rmnet_info.rx_urb_size;
358             profile->qmap_version = profile->rmnet_info.qmap_version;
359 
360             dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s",
361                 profile->qmap_mode, profile->muxid, profile->qmapnet_adapter);
362         }
363 
364         goto _out;
365     }
366 
367 _out:
368     return 0;
369 }
370 
ql_qmap_mode_detect(PROFILE_T * profile)371 int ql_qmap_mode_detect(PROFILE_T *profile) {
372     if (profile->software_interface == SOFTWARE_MBIM) {
373         if (profile->hardware_interface == HARDWARE_USB)
374             return ql_mbim_usb_vlan_mode_detect(profile);
375         else if (profile->hardware_interface == HARDWARE_PCIE)
376             return ql_mbim_mhi_qmap_mode_detect(profile);
377     } else if (profile->software_interface == SOFTWARE_QMI) {
378         return ql_qmi_qmap_mode_detect(profile);
379     }
380     return 0;
381 }
382