* Conexant AccessRunner ioctl call Copyright (C) 2003 Josep Comas 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Author : Josep Comas Creation : 24/1/2003 Description: This program does ioctl calls to Conexant driver. Log: 28/4/2003 Josep Comas Added support for Amigo AMX-CA86U and Olitec V3 30/4/2003 Josep Comas Added ioctls start and stop ADSL line 1/5/2003 Josep Comas Added support for Olitec V2 3/5/2003 Josep Comas Showing more information 5/5/2003 Josep Comas Update to work with libusb-0.1.7 3/6/2003 Josep Comas Added support for Amigo AMX-CA80U-2M Added more info 13/6/2003 Josep Comas Support for all modems in same executable 16/6/2003 Josep Comas Added units for attenuation, SNR and output power 1/9/2003 Josep Comas Added support for Zoom 5510 Added support for generic VID=0x0572, PID=0xCB01 and PID=0xCB06 6/9/2003 Josep Comas Added support for Draytek Vigor 318 */ #include #include #include #include #include #include #include #include #include /* translation files */ #define TF_CODE "cxioctl" /* defined in ANSI T1.413-1998 Annex D */ const char *adsl_chip_vendors[] = { "not allocated", "not allocated", "Westell, Inc.", "ECI Telecom", "Texas Instruments", "Intel", "Amati Communcations Corp.", "General Data Communications, Inc.", "Level One Communications", "Crystal Semiconductor", "Lucent Technologies", "Aware, Inc.", "Brooktree", "NEC", "Samsung", "Northern Telecom, Inc.", "PairGain Technologies", "Paradyne", "Adtran", "INC", "ADC Telecommunications", "Motorola", "IBM Corp.", "Newbridge Network Corp.", "DSC", "Teltrend", "Exar Corp.", "Siemens Telecom Networks", "Analog Devices", "Nokia", "Ericsson Information Systems", "Tellabs Operations, Inc.", "Orckit Communications, Inc.", "AWA", "Alcatel Network Systems, Inc.", "National Semiconductor Corp.", "Italtel", "SAT - Société Anonyme de Télécommunications", "Fujitsu Network Trans. Systems", "MITEL", "Conklin Corp.", "Diamond Lane", "Cabletron Systems, Inc.", "Davicom Semiconductor, Inc.", "Metalink", "Pulsecom", "US Robotics", "AG Communications Systems", "Rockwell", "Harris", "Hayes Microcomputer Products, Inc.", "Co-optic", "Netspeed, Inc.", "3-Com", "Copper Mountain, Inc", "Silicon Automation Systems, Ltd", "Ascom", "Globespan Semiconductor, Inc.", "STMicroelectronics", "Coppercom", "Compaq Computer Corp.", "Integrated Technology Express", "Bay Networks, Inc.", "Next Level Communications", "Multi-Tech Systems, Inc.", "AMD", "Sumitomo Electric", "Philips M&N Systems", "Efficient Networks, Inc.", "Interspeed", "Cisco Systems", "Tollgrade Communications, Inc.", "Cayman Systems", "FlowPoint Corp.", "I.C.COM", "Matsushita", "Siemens Semiconductor", "Digital Link", "Digitel", "Alcatel Microelectronics", "Centillium Corp.", "Applied Digital Access, Inc.", "Smart Link, Ltd." }; /* struct to call to Conexant kernel driver (module) */ struct usbdevfs_ioctl { int ifno; int ioctl_code; void *data; }; /* USBDEVFS IOCTL to call to Conexant kernel driver (module) */ #define USBDEVFS_IOCTL _IOWR('U', 18, struct usbdevfs_ioctl) /* struct to fill with info provided by Conexant kernel driver (module) */ struct udsl_modem_info { // version unsigned char mod_major; unsigned char mod_minor; unsigned char mod_release; unsigned char mod_speed; int hard_version; // controller version char firm_version[5]; unsigned char mac[6]; // transmit/configuration unsigned int atm_cell_tx; unsigned int atm_cell_rx; unsigned int oam_loopback; short vpi; int vci; //state int link_status; int line_status; unsigned int open_mode; unsigned int operational_mode; //modulation unsigned int data_path; unsigned int startup_attempts; unsigned int line_startable; unsigned int link_lost; int down_bitrate; int up_bitrate; unsigned int adsl_headend; unsigned int adsl_headend_env; //advanced unsigned char extended_info; int up_snr_margin; int down_snr_margin; unsigned int up_attenuation; unsigned int down_attenuation; int transmitter_power; unsigned int up_bits_frame; unsigned int down_bits_frame; unsigned int up_crc_errors; unsigned int down_crc_errors; unsigned int up_fec_errors; unsigned int down_fec_errors; unsigned int up_hec_errors; unsigned int down_hec_errors; } udsl_modem_info_t; /* IOCTL codes when call to Conexant kernel driver (module) */ #define IOCTL_START 1 #define IOCTL_STOP 2 #define IOCTL_INFO _IOWR('U', 3, struct udsl_modem_info) #define IOCTL_ADSL_LINE_START 4 #define IOCTL_ADSL_LINE_STOP 5 #define IOCTL_START_EXTENDED_INFO 6 #define IOCTL_STOP_EXTENDED_INFO 7 #define IOCTL_CLEAR_COUNTERS 8 /* check if a file exists */ int file_exists(const char *filename) { struct stat info_file; return stat(filename, &info_file) == 0; } /* show printable char */ void print_char(unsigned char c) { if (c >= ' ' && c < 0x7f) printf("%c", c); else printf("."); } /* check if it is a known modem */ int check_modem(unsigned int vid, unsigned int pid) { /* Vendor = Conexant, Product = ADSL modem (Euphrates project) */ if (vid == 0x0572 && pid == 0xcafe) return 1; /* Vendor = Olitec, Product = ADSL modem version 2 */ else if (vid == 0x08e3 && pid == 0x0100) return 2; /* Vendor = Olitec, Product = ADSL modem version 3 */ else if (vid == 0x08e3 && pid == 0x0102) return 3; /* Vendor = Trust/Amigo Technology Co., Product = AMX-CA86U */ else if (vid == 0x0eb0 && pid == 0x3457) return 4; /* Vendor = Conexant, Product = ADSL modem (Hasbani project) */ /* Used for: Vendor = Amigo Technology Co. Product = AMX-CA80U-2M Vendor = E-Tech Product = USB ADSL Modem */ else if (vid == 0x0572 && pid == 0xcb00) return 5; /* Used for: Vendor = Product = */ else if (vid == 0x0572 && pid == 0xcb01) return 5; /* Used for: Vendor = Etec Product = USB ADSL Modem Vendor = Aethra Product = Starmodem USB */ else if (vid == 0x0572 && pid == 0xcb06) return 5; /* Vendor = Draytek, Product = Vigor 318 */ else if (vid == 0x0675 && pid == 0x0200) return 5; /* Vendor = Zoom, Product = 5510 */ else if (vid == 0x1803 && pid == 0x5510) return 6; return -1; } int main(int argc, char *argv[]) { /* struct to call to Conexant kernel driver (module) */ struct usbdevfs_ioctl u_ioctl; /* struct where put info provided by Conexant kernel driver (module) */ struct udsl_modem_info modem_info; /* bus structures variables */ struct usb_bus * bus; struct usb_device * dev; struct usb_device * adsl_dev = NULL; usb_dev_handle * adsl_handle; /* boolean value */ int goon; /* result code */ int r; /* counter */ int i; /* init locale */ setlocale(LC_ALL, ""); //if (file_exists("./locale")) // bindtextdomain(TF_CODE, "./locale"); /* set directory for a domain (source code messages) */ //else bindtextdomain(TF_CODE, "/usr/share/locale"); /* set directory for a domain (source code messages) */ textdomain(TF_CODE); /* set domain */ /* show program information */ printf(gettext("Conexant AccessRunner ioctl call.")); printf(" 6/9/2003\n"); printf("Josep Comas \n"); printf("See credits in documentation\n\n"); /* check parameters */ if (argc < 2) { printf(gettext("Usage: %s ioctl_command\n"), argv[0]); printf(gettext("\nIOCTL commands:\n")); printf(gettext(" 1 (start, enable receive data in driver)\n")); printf(gettext(" 2 (stop, disable receive data in driver)\n")); printf(gettext(" 3 (info about modem)\n")); printf(gettext(" 4 (start ADSL line)\n")); printf(gettext(" 5 (stop ADSL line)\n")); printf(gettext(" 6 (start getting additional info when using normal speed mode in driver)\n")); printf(gettext(" 7 (stop getting additional info when using normal speed mode in driver)\n")); printf(gettext(" 8 (clear counters)\n")); printf(gettext("\nExamples:\n")); printf(gettext(" Enable receive data in driver: %s 1\n"), argv[0]); printf(gettext(" Disable receive data in driver: %s 2\n"), argv[0]); printf(gettext(" Show info about modem provided by driver: %s 3\n"), argv[0]); return -1; } if (strcmp(argv[1], "1") && strcmp(argv[1], "2") && strcmp(argv[1], "3") && strcmp(argv[1], "4") && strcmp(argv[1], "5") && strcmp(argv[1], "6") && strcmp(argv[1], "7") && strcmp(argv[1], "8")) { printf(gettext("Error: invalid command: %s\n"), argv[1]); return -1; } /* init USB bus and find devices */ usb_init(); if (usb_find_busses() < 0) { printf(gettext("Error: I can't find busses\n")); return -1; } if (usb_find_devices() < 0) { printf(gettext("Error: I can't find devices\n")); return -1; } /* search first Conexant AccessRunner */ bus = usb_busses; goon = 1; while (bus && goon) { dev = bus->devices; while (dev && goon) { if (check_modem(dev->descriptor.idVendor, dev->descriptor.idProduct) > 0) { goon = 0; adsl_dev = dev; } else dev = dev->next; } if (goon) bus = bus->next; } if (adsl_dev == NULL) { printf(gettext("Error: I didn't find ADSL modem\n")); return -1; } printf(gettext("I found ADSL modem with VendorID = %04x & ProductID = %04x\n"), adsl_dev->descriptor.idVendor, adsl_dev->descriptor.idProduct); /* connect to ADSL modem */ adsl_handle = usb_open(adsl_dev); if (adsl_handle == NULL) { printf(gettext("Error: Couldn't get device handle for ADSL modem\n")); return -1; } if (usb_set_configuration(adsl_handle, 1) < 0) { printf("Error: usb_set_configuration: %s\n", usb_strerror()); return -1; } u_ioctl.ifno = 0; if (argv[1][0] == '1') { u_ioctl.ioctl_code = IOCTL_START; u_ioctl.data = NULL; } else if (argv[1][0] == '2') { u_ioctl.ioctl_code = IOCTL_STOP; u_ioctl.data = NULL; } else if (argv[1][0] == '3') { u_ioctl.ioctl_code = IOCTL_INFO; u_ioctl.data = &modem_info; } else if (argv[1][0] == '4') { u_ioctl.ioctl_code = IOCTL_ADSL_LINE_START; u_ioctl.data = NULL; } else if (argv[1][0] == '5') { u_ioctl.ioctl_code = IOCTL_ADSL_LINE_STOP; u_ioctl.data = NULL; } else if (argv[1][0] == '6') { u_ioctl.ioctl_code = IOCTL_START_EXTENDED_INFO; u_ioctl.data = NULL; } else if (argv[1][0] == '7') { u_ioctl.ioctl_code = IOCTL_STOP_EXTENDED_INFO; u_ioctl.data = NULL; } else if (argv[1][0] == '8') { u_ioctl.ioctl_code = IOCTL_CLEAR_COUNTERS; u_ioctl.data = NULL; } r = ioctl(adsl_handle->fd, USBDEVFS_IOCTL, &u_ioctl); if (r < 0) { printf(gettext("Error in ioctl call, status = %d\n"), r); usb_close(adsl_handle); return -1; } else if (argv[1][0] == '3') { printf("\n"); /* versions */ printf(gettext("Versions:\n")); printf(gettext(" Module version (driver) = %d.%d.%d (%s speed)\n"), modem_info.mod_major, modem_info.mod_minor, modem_info.mod_release, modem_info.mod_speed==1?gettext("max"):gettext("normal")); printf(gettext(" Hardware version = %u\n"), modem_info.hard_version); printf(" Firmware version = "); for (i = 0; i < sizeof(modem_info.firm_version); i++) printf("%c", modem_info.firm_version[i]); printf("\n"); printf(gettext(" MAC address = ")); for (i = 0; i < 6; i++) { printf("%02x", modem_info.mac[i]); if (i != 5) printf("."); } printf("\n"); printf("\n"); /* transmit/configuration */ printf(gettext("Transmit/configuration:\n")); printf(gettext(" ATM cells transmited = %u\n"), modem_info.atm_cell_tx); printf(gettext(" ATM cells received = %u\n"), modem_info.atm_cell_rx); printf(gettext(" OAM loopback cells = %u\n"), modem_info.oam_loopback); printf(" VPI = %d\n", modem_info.vpi); printf(" VCI = %d\n", modem_info.vci); printf("\n"); /* state */ printf(gettext("State:\n")); printf(gettext(" Link status = 0x%04x ("), modem_info.link_status); switch (modem_info.link_status) { case LINK_STATUS_NOT_CONNECTED: printf(gettext("not established")); break; case LINK_STATUS_CONNECTED: printf(gettext("connected")); break; case LINK_STATUS_LOST: printf(gettext("lost")); break; default: printf(gettext("unknown")); break; }; printf(")\n"); printf(gettext(" Line status = 0x%04x ("), modem_info.line_status); switch (modem_info.line_status) { case LINE_STATUS_DOWN: printf(gettext("down")); break; case LINE_STATUS_ATTEMPTING_TO_ACTIVATE: printf(gettext("attempting to activate")); break; case LINE_STATUS_TRAINING: printf(gettext("training")); break; case LINE_STATUS_CHANNEL_ANALYSIS: printf(gettext("channel analysis")); break; case LINE_STATUS_UP: printf(gettext("up")); break; case LINE_STATUS_WAITING: printf(gettext("waiting")); break; case LINE_STATUS_INITIALIZING: printf(gettext("initializing")); break; default: printf(gettext("unknown")); break; }; printf(")\n"); printf(gettext(" Open mode = ")); switch (modem_info.open_mode) { case ADSL_OPEN_AUTO1: printf(gettext("auto selection, G.Handshake")); break; case ADSL_OPEN_AUTO2: printf(gettext("auto selection, T1.413")); break; case ADSL_OPEN_HAND: printf(gettext("G.Handshake")); break; case ADSL_OPEN_ANSI: printf(gettext("ANSI T1.413")); break; case ADSL_OPEN_GDMT: printf(gettext("ITU-T G.992.1 (G.DMT)")); break; case ADSL_OPEN_GLITE: printf(gettext("ITU-T G.992.2 (G.LITE)")); break; default: printf(gettext("unknown")); break; } printf("\n"); printf(gettext(" Operational mode = ")); switch (modem_info.operational_mode) { case ADSL_ANSI: printf(gettext("ANSI T1.413")); break; case ADSL_GDMT: printf(gettext("ITU-T G.992.1 (G.DMT)")); break; case ADSL_GLITE: printf(gettext("ITU-T G.992.2 (G.LITE)")); break; default: printf(gettext("unknown")); break; } printf("\n"); /* printf(gettext("Data path = 0x%02x ("), modem_info.data_path); switch (modem_info.data_path) { case FastPath: printf("fastpath"); break; case InterleavedPath: printf("interleaved"); break; default: printf(gettext("unknown")); break; }; printf(")\n"); */ printf(gettext(" Startup attempts = %u\n"), modem_info.startup_attempts); printf(gettext(" Line startable = %u\n"), modem_info.line_startable); printf(gettext(" Link lost = %u\n"), modem_info.link_lost); printf(gettext(" Downstream bitrate (Kbits/s) = %u\n"), modem_info.down_bitrate); printf(gettext(" Upstream bitrate (Kbits/s) = %u\n"), modem_info.up_bitrate); printf(gettext(" ADSL headend = 0x%04x"), modem_info.adsl_headend); if (modem_info.adsl_headend < (sizeof(adsl_chip_vendors)/sizeof(int))) printf(" (%s)", adsl_chip_vendors[modem_info.adsl_headend]); printf("\n"); printf(gettext(" ADSL headend environment = %u\n"), modem_info.adsl_headend_env); printf("\n"); /* advanced */ if (modem_info.extended_info != 1) printf(gettext("Extended info not available\n")); else { printf(gettext("Extended info:\n")); printf(gettext(" up SNR margin (dB) = %4.2f\n"), modem_info.up_snr_margin/256.0); printf(gettext(" down SNR margin (dB) = %4.2f\n"), modem_info.down_snr_margin/256.0); printf(gettext(" up attenuation (dB) = %4.2f\n"), modem_info.up_attenuation/512.0); printf(gettext(" down attenuation (dB) = %4.2f\n"), modem_info.down_attenuation/512.0); printf(gettext(" transmitter power (dBm/Hz) = %d\n"), modem_info.transmitter_power-256); printf(gettext(" up bits per frame = %d\n"), modem_info.up_bits_frame); printf(gettext(" down bits per frame = %d\n"), modem_info.down_bits_frame); printf(gettext(" up crc errors = %d\n"), modem_info.up_crc_errors); printf(gettext(" down crc errors = %d\n"), modem_info.down_crc_errors); printf(gettext(" up fec errors = %d\n"), modem_info.up_fec_errors); printf(gettext(" down fec errors = %d\n"), modem_info.down_fec_errors); printf(gettext(" up hec errors = %d\n"), modem_info.up_hec_errors); printf(gettext(" down hec errors = %d\n"), modem_info.down_hec_errors); } } usb_close(adsl_handle); return 0; }