#include "QMIThread.h" //2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037 #include //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; }