/* * $Id: avmcapictrl.c,v 1.3 1997/12/07 20:02:22 calle Exp $ * * AVM-B1-ISDN driver for Linux. (Control-Utility) * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: avmcapictrl.c,v $ * Revision 1.3 1997/12/07 20:02:22 calle * prepared support for cardtype and different protocols * * Revision 1.2 1997/03/20 00:18:57 luethje * inserted the line #include in avmb1/avmcapictrl.c and imon/imon.c, * some bugfixes, new structure in isdnlog/isdnrep/isdnrep.c. * * Revision 1.1 1997/03/04 22:46:32 calle * Added program to add and download firmware to AVM-B1 card * * Revision 2.2 1997/02/12 09:31:39 calle * more verbose error messages * * Revision 1.1 1997/01/31 10:32:20 calle * Initial revision * * */ #include #include #include #include #include #include #include #include #include #include #include #include #include char *cmd; char *ctrldev; int arg_ofs; void usage(void) { fprintf(stderr, "usage: %s add [B1|M1|T1] (Add a new card)\n", cmd); fprintf(stderr, " or: %s load [contrnr [protocol [P2P]]] (load firmware)\n", cmd); fprintf(stderr, " or: %s reset [contrnr] (reset controller)\n", cmd); exit(1); } #define DP_NONE 0 #define DP_DSS1 1 #define DP_D64S 2 #define DP_D64S2 3 #define DP_D64SD 4 #define DP_DS01 5 #define DP_DS02 6 #define DP_CT1 7 #define DP_VN3 8 #define DP_AUSTEL 9 #define DP_5ESS 10 /* need SPID,SPID2,DN,DN2 */ #define DP_NI1 11 /* need SPID,SPID2,DN,DN2 */ #define DP_DSS1MOBIL 12 #define DP_1TR6MOBIL 13 #define DP_GSM 14 #define DP_1TR6 15 static struct pmap { char *name; int protocol; } pmap[] = { { "DSS1", DP_DSS1 }, { "D64S", DP_D64S }, { "D64S2", DP_D64S2 }, { "D64SD", DP_D64SD }, { "DS01", DP_DS01 }, { "DS02", DP_DS02 }, { "CT1", DP_CT1 }, { "VN3", DP_VN3 }, { "AUSTEL", DP_AUSTEL }, { "5ESS", DP_5ESS }, { "NI1", DP_NI1 }, { "DSS1MOBIL", DP_DSS1MOBIL }, { "1TR6MOBIL", DP_1TR6MOBIL }, { "GSM", DP_GSM }, { "1TR6", DP_1TR6 }, { 0 }, }; static int dchan_protocol(char *pname) { struct pmap *p; for (p=pmap; p->name; p++) { if (strcasecmp(pname, p->name) == 0) return p->protocol; } return DP_NONE; } static char patcharea[2048]; static int patchlen = 0; static void addpatchvalue(char *name, char *value, int len) { int nlen = strlen(name); if (patchlen + nlen + len + 2 >= sizeof(patcharea)) { fprintf(stderr, "%s: can't add patchvalue %s\n" , cmd, name); exit(3); } memcpy(&patcharea[patchlen], name, nlen); patchlen += nlen; patcharea[patchlen++] = 0; memcpy(&patcharea[patchlen], value, len); patcharea[patchlen++] = 0; patcharea[patchlen+1] = 0; } int set_configuration(avmb1_t4file *t4config, int protocol, int p2p) { addpatchvalue("AutoFrame", "\001", 1); addpatchvalue("WATCHDOG", "1", 1); addpatchvalue("CWEnable", "1", 1); switch (protocol) { case DP_NONE: break; case DP_DSS1: break; case DP_D64S: addpatchvalue("MpriOneChannel", "1", 1); case DP_D64S2: case DP_D64SD: p2p = 0; addpatchvalue("TEI", "\000", 1); addpatchvalue("FV2", "2", 1); addpatchvalue("MpriD64S", "1", 1); break; case DP_DS01: addpatchvalue("MpriOneChannel", "1", 1); case DP_DS02: p2p = 0; addpatchvalue("TEI", "\000", 1); addpatchvalue("FV2", "1", 1); break; case DP_CT1: addpatchvalue("PROTOCOL", "\001", 1); break; case DP_VN3: addpatchvalue("PROTOCOL", "\002", 1); break; case DP_AUSTEL: addpatchvalue("PROTOCOL", "\004", 1); break; case DP_NI1: addpatchvalue("PROTOCOL", "\003", 1); break; /* $$$ */ case DP_5ESS: addpatchvalue("PROTOCOL", "\005", 1); break; /* $$$ */ case DP_DSS1MOBIL: addpatchvalue("PatchMobileMode", "0", 1); break; case DP_1TR6MOBIL: addpatchvalue("PatchMobileMode", "0", 1); break; case DP_GSM: addpatchvalue("MpriOneChannel", "1", 1); addpatchvalue("MpriNoV42bis", "1", 1); break; case DP_1TR6: addpatchvalue("MpriSemi", "1", 1); break; default: return -1; } if (p2p) { addpatchvalue("P2P", "\001", 1); addpatchvalue("TEI", "\000", 1); addpatchvalue("MpriDDI", "1", 1); } t4config->len = patchlen+1; t4config->data = patcharea; return 0; } int validports[] = {0x150, 0x250, 0x300, 0x340, 0}; int validirqs[] = { 3, 4, 5, 6, 7, 9, 10, 11, 12, 15, 0}; int main(int argc, char **argv) { int fd; int ac; capi_manufacturer_cmd ioctl_s; avmb1_extcarddef newcard; avmb1_loadandconfigdef ldef; avmb1_resetdef rdef; avmb1_getdef gdef; int newdriver; cmd = strrchr(argv[0], '/'); cmd = (cmd == NULL) ? argv[0] : ++cmd; if (argc > 1) { arg_ofs = 1; } else usage(); ac = argc - (arg_ofs - 1); fd = open("/dev/capi20", O_RDWR); if (fd < 0) { switch (errno) { case ENOENT: perror("Device file /dev/capi20 missing, use instdev"); exit(2); case ENODEV: perror("device capi20 not registered"); fprintf(stderr, "look in /proc/devices.\n"); fprintf(stderr, "maybe the devicefiles are installed with a wrong majornumber,\n"); fprintf(stderr, "or you linux kernel version only supports 64 char device (check /usr/include/linux/major.h)\n"); exit(2); } perror("/dev/capi20"); exit(-1); } gdef.contr = 0; ioctl_s.cmd = AVMB1_GET_CARDINFO; ioctl_s.data = &gdef; newdriver = 0; if ((ioctl(fd, CAPI_MANUFACTURER_CMD, &ioctl_s)) < 0) { if (errno != EINVAL) newdriver = 1; } else { newdriver = 1; } if (!strcasecmp(argv[arg_ofs], "add")) { int port, irq, cardtype; if (ac >= 4) { int i; sscanf(argv[arg_ofs + 1], "%i", &port); sscanf(argv[arg_ofs + 2], "%i", &irq); if (argv[arg_ofs + 3]) { if (strcasecmp(argv[arg_ofs + 3],"B1") == 0) { cardtype = AVM_CARDTYPE_B1; } else if (strcasecmp(argv[arg_ofs + 3],"M1") == 0) { cardtype = AVM_CARDTYPE_M1; } else if (strcasecmp(argv[arg_ofs + 3],"T1") == 0) { cardtype = AVM_CARDTYPE_T1; } else { fprintf(stderr, "%s: illegal cardtype \"%s\"\n", cmd, argv[arg_ofs + 3]); fprintf(stderr, "%s: try one of B1,M1,T1", cmd); exit(-1); } } else { cardtype = AVM_CARDTYPE_B1; } for (i = 0; validports[i] && port != validports[i]; i++); if (!validports[i]) { fprintf(stderr, "%s: illegal io-addr 0x%x\n", cmd, port); fprintf(stderr, "%s: try one of 0x%x", cmd, validports[0]); for (i = 1; validports[i]; i++) fprintf(stderr, ", 0x%x", validports[i]); fprintf(stderr, "\n"); exit(-1); } for (i = 0; validirqs[i] && irq != validirqs[i]; i++); if (!validirqs[i]) { fprintf(stderr, "%s: illegal irq %d\n", cmd, irq); fprintf(stderr, "%s: try one of %d", cmd, validirqs[0]); for (i = 1; validirqs[i]; i++) fprintf(stderr, ", %d", validirqs[i]); fprintf(stderr, "\n"); exit(-1); } newcard.port = port; newcard.irq = irq; newcard.cardtype = cardtype; if (!newdriver && cardtype != AVM_CARDTYPE_B1) { fprintf(stderr, "%s: only B1 supported by kernel driver, sorry\n", cmd); exit(1); } if (newdriver) ioctl_s.cmd = AVMB1_ADDCARD_WITH_TYPE; else ioctl_s.cmd = AVMB1_ADDCARD; ioctl_s.data = &newcard; if ((ioctl(fd, CAPI_MANUFACTURER_CMD, &ioctl_s)) < 0) { perror("ioctl ADDCARD"); exit(-1); } close(fd); return 0; } } if (!strcasecmp(argv[arg_ofs], "load")) { struct stat st; int codefd; int contr = 1; int protocol = 0; int p2p = 0; if (ac > 3) contr = atoi(argv[arg_ofs + 2]); if (ac > 4) { if (!newdriver) { fprintf(stderr, "%s: need newer kernel driver to set protocol\n", cmd); exit(1); } protocol = dchan_protocol(argv[arg_ofs + 3]); if (protocol < 0) { fprintf(stderr,"invalid protocol \"%s\"\n", argv[arg_ofs + 3]); /* show_protocols(); */ exit(1); } } if (ac > 5) { if (strcasecmp(argv[arg_ofs + 4], "P2P") == 0) { p2p = 1; } else { fprintf(stderr,"parameter should be P2P not \"%s\"\n", argv[arg_ofs + 4]); exit(1); } } if (stat(argv[arg_ofs + 1], &st)) { perror(argv[arg_ofs + 1]); exit(2); } if (!(codefd = open(argv[arg_ofs + 1], O_RDONLY))) { perror(argv[arg_ofs + 1]); exit(2); } ldef.contr = contr; ldef.t4file.len = st.st_size; ldef.t4file.data = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, codefd, 0); if (ldef.t4file.data == (unsigned char *) -1) { perror("mmap"); exit(2); } ldef.t4config.len = 0; ldef.t4config.data = 0; if (protocol || p2p) set_configuration(&ldef.t4config, protocol, p2p); printf("Loading Bootcode %s ... ", argv[arg_ofs + 1]); fflush(stdout); if (newdriver) ioctl_s.cmd = AVMB1_LOAD_AND_CONFIG; else ioctl_s.cmd = AVMB1_LOAD; ioctl_s.data = &ldef; if ((ioctl(fd, CAPI_MANUFACTURER_CMD, &ioctl_s)) < 0) { perror("\nioctl LOAD"); exit(2); } munmap(ldef.t4file.data, ldef.t4file.len); close(codefd); close(fd); printf("done\n"); return 0; } if (!strcasecmp(argv[arg_ofs], "reset")) { int contr = 1; if (ac > 2) contr = atoi(argv[arg_ofs + 1]); rdef.contr = contr; ioctl_s.cmd = AVMB1_RESETCARD; ioctl_s.data = &rdef; if ((ioctl(fd, CAPI_MANUFACTURER_CMD, &ioctl_s)) < 0) { perror("\nioctl RESET"); exit(2); } close(fd); return 0; } usage(); return 0; }