static int mi_e1_setup(struct e1inp_line *line, int release_l2) { struct misdn_line *mline = line->driver_data; int ts, ret; mline->dummy_dchannel = -1; if (mline->use_userspace_lapd) { /* Open dummy d-channel in order to use b-channels. * Also it is required to define the mode. */ if (mline->dummy_dchannel < 0) { struct sockaddr_mISDN addr; mline->dummy_dchannel = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_NT_E1); if (mline->dummy_dchannel < 0) { fprintf(stderr, "%s could not open socket %s\n", __func__, strerror(errno)); return mline->dummy_dchannel; } memset(&addr, 0, sizeof(addr)); addr.family = AF_ISDN; addr.dev = line->port_nr; addr.channel = 0; addr.sapi = 0; addr.tei = GROUP_TEI; ret = bind(mline->dummy_dchannel, (struct sockaddr *) &addr, sizeof(addr)); if (ret < 0) { fprintf(stderr, "could not bind l2 socket %s\n", strerror(errno)); return -EIO; } } } /* TS0 is CRC4, don't need any fd for it */ for (ts = 1; ts < NUM_E1_TS; ts++) { unsigned int idx = ts-1; struct e1inp_ts *e1i_ts = &line->ts[idx]; struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd; struct sockaddr_mISDN addr; bfd->data = line; bfd->priv_nr = ts; bfd->cb = misdn_fd_cb; switch (e1i_ts->type) { case E1INP_TS_TYPE_NONE: continue; break; case E1INP_TS_TYPE_SIGN: if (mline->use_userspace_lapd) bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_HDLC); else bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_NT); bfd->when = BSC_FD_READ; break; case E1INP_TS_TYPE_TRAU: bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW); /* We never include the mISDN B-Channel FD into the * writeset, since it doesn't support poll() based * write flow control */ bfd->when = BSC_FD_READ; break; } if (bfd->fd < 0) { fprintf(stderr, "%s could not open socket %s\n", __func__, strerror(errno)); return bfd->fd; } memset(&addr, 0, sizeof(addr)); addr.family = AF_ISDN; addr.dev = line->port_nr; switch (e1i_ts->type) { case E1INP_TS_TYPE_SIGN: if (mline->use_userspace_lapd) { addr.channel = ts; e1i_ts->lapd = lapd_instance_alloc(1, misdn_write_msg, bfd, e1inp_dlsap_up, e1i_ts, &lapd_profile_abis); } else { addr.channel = 0; /* SAPI not supported yet in kernel */ //addr.sapi = e1inp_ts->sign.sapi; addr.sapi = 0; addr.tei = GROUP_TEI; } break; case E1INP_TS_TYPE_TRAU: addr.channel = ts; break; default: DEBUGP(DLMI, "unsupported E1 TS type: %u\n", e1i_ts->type); break; } ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr)); if (ret < 0) { fprintf(stderr, "could not bind l2 socket %s\n", strerror(errno)); return -EIO; } if (e1i_ts->type == E1INP_TS_TYPE_SIGN) { if (!mline->use_userspace_lapd) { ret = ioctl(bfd->fd, IMCLEAR_L2, &release_l2); if (ret < 0) { fprintf(stderr, "could not send IOCTL IMCLEAN_L2 %s\n", strerror(errno)); return -EIO; } } else activate_bchan(line, ts, 1); } /* FIXME: only activate B-Channels once we start to * use them to conserve CPU power */ if (e1i_ts->type == E1INP_TS_TYPE_TRAU) activate_bchan(line, ts, 1); ret = osmo_fd_register(bfd); if (ret < 0) { fprintf(stderr, "could not register FD: %s\n", strerror(ret)); return ret; } } return 0; }
static int mi_e1_setup(struct e1inp_line *line, int release_l2) { int ts, ret; /* TS0 is CRC4, don't need any fd for it */ for (ts = 1; ts < NUM_E1_TS; ts++) { unsigned int idx = ts-1; struct e1inp_ts *e1i_ts = &line->ts[idx]; struct bsc_fd *bfd = &e1i_ts->driver.misdn.fd; struct sockaddr_mISDN addr; bfd->data = line; bfd->priv_nr = ts; bfd->cb = misdn_fd_cb; switch (e1i_ts->type) { case E1INP_TS_TYPE_NONE: continue; break; case E1INP_TS_TYPE_SIGN: bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_NT); bfd->when = BSC_FD_READ; break; case E1INP_TS_TYPE_TRAU: bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW); /* We never include the mISDN B-Channel FD into the * writeset, since it doesn't support poll() based * write flow control */ bfd->when = BSC_FD_READ; break; } if (bfd->fd < 0) { fprintf(stderr, "%s could not open socket %s\n", __func__, strerror(errno)); return bfd->fd; } memset(&addr, 0, sizeof(addr)); addr.family = AF_ISDN; addr.dev = line->num; switch (e1i_ts->type) { case E1INP_TS_TYPE_SIGN: addr.channel = 0; /* SAPI not supported yet in kernel */ //addr.sapi = e1inp_ts->sign.sapi; addr.sapi = 0; addr.tei = GROUP_TEI; break; case E1INP_TS_TYPE_TRAU: addr.channel = ts; break; default: DEBUGP(DMI, "unsupported E1 TS type: %u\n", e1i_ts->type); break; } ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr)); if (ret < 0) { fprintf(stderr, "could not bind l2 socket %s\n", strerror(errno)); return -EIO; } if (e1i_ts->type == E1INP_TS_TYPE_SIGN) { ret = ioctl(bfd->fd, IMCLEAR_L2, &release_l2); if (ret < 0) { fprintf(stderr, "could not send IOCTL IMCLEAN_L2 %s\n", strerror(errno)); return -EIO; } } /* FIXME: only activate B-Channels once we start to * use them to conserve CPU power */ if (e1i_ts->type == E1INP_TS_TYPE_TRAU) activate_bchan(line, ts, 1); ret = bsc_register_fd(bfd); if (ret < 0) { fprintf(stderr, "could not register FD: %s\n", strerror(ret)); return ret; } } return 0; }