📄 kcapi.c
字号:
int i; if (!VALID_APPLID(applid) || APPL(applid)->releasing) return CAPI_ILLAPPNR; APPL(applid)->releasing++; skb_queue_purge(&APPL(applid)->recv_queue); for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate != CARD_RUNNING) continue; APPL(applid)->releasing++; cards[i].driver->release_appl(&cards[i], applid); } APPL(applid)->releasing--; if (APPL(applid)->releasing <= 0) { APPL(applid)->signal = 0; APPL_MARK_FREE(applid); printk(KERN_INFO "kcapi: appl %d down\n", applid); } return CAPI_NOERROR;}static __u16 capi_put_message(__u16 applid, struct sk_buff *skb){ struct capi_ncci *np; __u32 contr; int showctl = 0; __u8 cmd, subcmd; if (ncards == 0) return CAPI_REGNOTINSTALLED; if (!VALID_APPLID(applid)) return CAPI_ILLAPPNR; if (skb->len < 12 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; contr = CAPIMSG_CONTROLLER(skb->data); if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) { contr = 1; if (CARD(contr)->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; } if (CARD(contr)->blocked) return CAPI_SENDQUEUEFULL; cmd = CAPIMSG_COMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data); if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { if ((np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0 && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0) return CAPI_SENDQUEUEFULL; CARD(contr)->nsentdatapkt++; APPL(applid)->nsentdatapkt++; if (CARD(contr)->traceflag > 2) showctl |= 2; } else { CARD(contr)->nsentctlpkt++; APPL(applid)->nsentctlpkt++; if (CARD(contr)->traceflag) showctl |= 2; } showctl |= (CARD(contr)->traceflag & 1); if (showctl & 2) { if (showctl & 1) { printk(KERN_DEBUG "kcapi: put [0x%lx] id#%d %s len=%u\n", (unsigned long) contr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { printk(KERN_DEBUG "kcapi: put [0x%lx] %s\n", (unsigned long) contr, capi_message2str(skb->data)); } } CARD(contr)->driver->send_message(CARD(contr), skb); return CAPI_NOERROR;}static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp){ struct sk_buff *skb; if (!VALID_APPLID(applid)) return CAPI_ILLAPPNR; if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0) return CAPI_RECEIVEQUEUEEMPTY; *msgp = skb; return CAPI_NOERROR;}static __u16 capi_set_signal(__u16 applid, void (*signal) (__u16 applid, void *param), void *param){ if (!VALID_APPLID(applid)) return CAPI_ILLAPPNR; APPL(applid)->signal = signal; APPL(applid)->param = param; return CAPI_NOERROR;}static __u16 capi_get_manufacturer(__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN]){ if (contr == 0) { strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR;}static __u16 capi_get_version(__u32 contr, struct capi_version *verp){ if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version)); return CAPI_NOERROR;}static __u16 capi_get_serial(__u32 contr, __u8 serial[CAPI_SERIAL_LEN]){ if (contr == 0) { strncpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN); return CAPI_NOERROR;}static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp){ if (contr == 0) { profp->ncontroller = ncards; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) return CAPI_REGNOTINSTALLED; memcpy((void *) profp, &CARD(contr)->profile, sizeof(struct capi_profile)); return CAPI_NOERROR;}static struct capi_driver *find_driver(char *name){ struct capi_driver *dp; spin_lock(&drivers_lock); for (dp = drivers; dp; dp = dp->next) if (strcmp(dp->name, name) == 0) break; spin_unlock(&drivers_lock); return dp;}#ifdef CONFIG_AVMB1_COMPATstatic int old_capi_manufacturer(unsigned int cmd, void *data){ avmb1_loadandconfigdef ldef; avmb1_extcarddef cdef; avmb1_resetdef rdef; avmb1_getdef gdef; struct capi_driver *driver; struct capi_ctr *card; capicardparams cparams; capiloaddata ldata; int retval; switch (cmd) { case AVMB1_ADDCARD: case AVMB1_ADDCARD_WITH_TYPE: if (cmd == AVMB1_ADDCARD) { if ((retval = copy_from_user((void *) &cdef, data, sizeof(avmb1_carddef)))) return retval; cdef.cardtype = AVM_CARDTYPE_B1; } else { if ((retval = copy_from_user((void *) &cdef, data, sizeof(avmb1_extcarddef)))) return retval; } cparams.port = cdef.port; cparams.irq = cdef.irq; cparams.cardnr = cdef.cardnr; switch (cdef.cardtype) { case AVM_CARDTYPE_B1: driver = find_driver("b1isa"); break; case AVM_CARDTYPE_T1: driver = find_driver("t1isa"); break; default: driver = 0; break; } if (!driver) { printk(KERN_ERR "kcapi: driver not loaded.\n"); return -EIO; } if (!driver->add_card) { printk(KERN_ERR "kcapi: driver has no add card function.\n"); return -EIO; } return driver->add_card(driver, &cparams); case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: if (cmd == AVMB1_LOAD) { if ((retval = copy_from_user((void *) &ldef, data, sizeof(avmb1_loaddef)))) return retval; ldef.t4config.len = 0; ldef.t4config.data = 0; } else { if ((retval = copy_from_user((void *) &ldef, data, sizeof(avmb1_loadandconfigdef)))) return retval; } if (!VALID_CARD(ldef.contr)) return -ESRCH; card = CARD(ldef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->driver->load_firmware == 0) { printk(KERN_DEBUG "kcapi: load: driver \%s\" has no load function\n", card->driver->name); return -ESRCH; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); return -EINVAL; } if (ldef.t4file.data == 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); return -EINVAL; } ldata.firmware.user = 1; ldata.firmware.data = ldef.t4file.data; ldata.firmware.len = ldef.t4file.len; ldata.configuration.user = 1; ldata.configuration.data = ldef.t4config.data; ldata.configuration.len = ldef.t4config.len; if (card->cardstate != CARD_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); return -EBUSY; } card->cardstate = CARD_LOADING; retval = card->driver->load_firmware(card, &ldata); if (retval) { card->cardstate = CARD_DETECTED; return retval; } while (card->cardstate != CARD_RUNNING) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; } return 0; case AVMB1_RESETCARD: if ((retval = copy_from_user((void *) &rdef, data, sizeof(avmb1_resetdef)))) return retval; if (!VALID_CARD(rdef.contr)) return -ESRCH; card = CARD(rdef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->cardstate == CARD_DETECTED) return 0; card->driver->reset_ctr(card); while (card->cardstate > CARD_DETECTED) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; } return 0; case AVMB1_GET_CARDINFO: if ((retval = copy_from_user((void *) &gdef, data, sizeof(avmb1_getdef)))) return retval; if (!VALID_CARD(gdef.contr)) return -ESRCH; card = CARD(gdef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; gdef.cardstate = card->cardstate; if (card->driver == find_driver("t1isa")) gdef.cardtype = AVM_CARDTYPE_T1; else gdef.cardtype = AVM_CARDTYPE_B1; if ((retval = copy_to_user(data, (void *) &gdef, sizeof(avmb1_getdef)))) return retval; return 0; case AVMB1_REMOVECARD: if ((retval = copy_from_user((void *) &rdef, data, sizeof(avmb1_resetdef)))) return retval; if (!VALID_CARD(rdef.contr)) return -ESRCH; card = CARD(rdef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; if (card->cardstate != CARD_DETECTED) return -EBUSY; card->driver->remove_ctr(card); while (card->cardstate != CARD_FREE) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) return -EINTR; } return 0; } return -EINVAL;}#endifstatic int capi_manufacturer(unsigned int cmd, void *data){ struct capi_ctr *card; int retval; switch (cmd) {#ifdef CONFIG_AVMB1_COMPAT case AVMB1_ADDCARD: case AVMB1_ADDCARD_WITH_TYPE: case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: case AVMB1_RESETCARD: case AVMB1_GET_CARDINFO: case AVMB1_REMOVECARD: return old_capi_manufacturer(cmd, data);#endif case KCAPI_CMD_TRACE: { kcapi_flagdef fdef; if ((retval = copy_from_user((void *) &fdef, data, sizeof(kcapi_flagdef)))) return retval; if (!VALID_CARD(fdef.contr)) return -ESRCH; card = CARD(fdef.contr); if (card->cardstate == CARD_FREE) return -ESRCH; card->traceflag = fdef.flag; printk(KERN_INFO "kcapi: contr %d set trace=%d\n", card->cnr, card->traceflag); return 0; } case KCAPI_CMD_ADDCARD: { struct capi_driver *driver; capicardparams cparams; kcapi_carddef cdef; if ((retval = copy_from_user((void *) &cdef, data, sizeof(cdef)))) return retval; cparams.port = cdef.port; cparams.irq = cdef.irq; cparams.membase = cdef.membase; cparams.cardnr = cdef.cardnr; cparams.cardtype = 0; cdef.driver[sizeof(cdef.driver)-1] = 0; if ((driver = find_driver(cdef.driver)) == 0) { printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", cdef.driver); return -ESRCH; } if (!driver->add_card) { printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); return -EIO; } return driver->add_card(driver, &cparams); } default: printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n", cmd); break; } return -EINVAL;}struct capi_interface avmb1_interface ={ capi_isinstalled, capi_register, capi_release, capi_put_message, capi_get_message, capi_set_signal, capi_get_manufacturer, capi_get_version, capi_get_serial, capi_get_profile, capi_manufacturer};/* ------------------------------------------------------------- *//* -------- Exported Functions --------------------------------- *//* ------------------------------------------------------------- */struct capi_interface *attach_capi_interface(struct capi_interface_user *userp){ struct capi_interface_user *p; MOD_INC_USE_COUNT; spin_lock(&capi_users_lock); for (p = capi_users; p; p = p->next) { if (p == userp) { spin_unlock(&capi_users_lock); printk(KERN_ERR "kcapi: double attach from %s\n", userp->name); MOD_DEC_USE_COUNT; return 0; } } userp->next = capi_users; capi_users = userp; spin_unlock(&capi_users_lock); printk(KERN_NOTICE "kcapi: %s attached\n", userp->name); return &avmb1_interface;}int detach_capi_interface(struct capi_interface_user *userp){ struct capi_interface_user **pp; spin_lock(&capi_users_lock); for (pp = &capi_users; *pp; pp = &(*pp)->next) { if (*pp == userp) { *pp = userp->next; spin_unlock(&capi_users_lock); userp->next = 0; printk(KERN_NOTICE "kcapi: %s detached\n", userp->name); MOD_DEC_USE_COUNT; return 0; } } spin_unlock(&capi_users_lock); printk(KERN_ERR "kcapi: double detach from %s\n", userp->name); return -1;}/* ------------------------------------------------------------- *//* -------- Init & Cleanup ------------------------------------- *//* ------------------------------------------------------------- */EXPORT_SYMBOL(attach_capi_interface);EXPORT_SYMBOL(detach_capi_interface);EXPORT_SYMBOL(attach_capi_driver);EXPORT_SYMBOL(detach_capi_driver);/* * init / exit functions */static int __init kcapi_init(void){ char *p; char rev[32]; MOD_INC_USE_COUNT; skb_queue_head_init(&recv_queue); tq_state_notify.routine = notify_handler; tq_state_notify.data = 0; tq_recv_notify.routine = recv_handler; tq_recv_notify.data = 0; proc_capi_init(); if ((p = strchr(revision, ':')) != 0 && p[1]) { strncpy(rev, p + 2, sizeof(rev)); rev[sizeof(rev)-1] = 0; if ((p = strchr(rev, '$')) != 0 && p > rev) *(p-1) = 0; } else strcpy(rev, "1.0");#ifdef MODULE printk(KERN_NOTICE "CAPI-driver Rev %s: loaded\n", rev);#else printk(KERN_NOTICE "CAPI-driver Rev %s: started\n", rev);#endif MOD_DEC_USE_COUNT; return 0;}static void __exit kcapi_exit(void){ char rev[10]; char *p; if ((p = strchr(revision, ':'))) { strcpy(rev, p + 1); p = strchr(rev, '$'); *p = 0; } else { strcpy(rev, "1.0"); } proc_capi_exit(); printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev);}module_init(kcapi_init);module_exit(kcapi_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -