drivers: isdn: use new hex_to_bin() method
[safe/jmp/linux-2.6] / drivers / isdn / gigaset / capi.c
index d1afac2..ac4cfee 100644 (file)
@@ -12,7 +12,8 @@
  */
 
 #include "gigaset.h"
-#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/isdn/capilli.h>
 #include <linux/isdn/capicmd.h>
 #include <linux/isdn/capiutil.h>
@@ -169,31 +170,6 @@ static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param,
 }
 
 /*
- * check for legal hex digit
- */
-static inline int ishexdigit(char c)
-{
-       if (c >= '0' && c <= '9')
-               return 1;
-       if (c >= 'A' && c <= 'F')
-               return 1;
-       if (c >= 'a' && c <= 'f')
-               return 1;
-       return 0;
-}
-
-/*
- * convert hex to binary
- */
-static inline u8 hex2bin(char c)
-{
-       int result = c & 0x0f;
-       if (c & 0x40)
-               result += 9;
-       return result;
-}
-
-/*
  * convert an IE from Gigaset hex string to ETSI binary representation
  * including length byte
  * return value: result length, -1 on error
@@ -202,9 +178,9 @@ static int encode_ie(char *in, u8 *out, int maxlen)
 {
        int l = 0;
        while (*in) {
-               if (!ishexdigit(in[0]) || !ishexdigit(in[1]) || l >= maxlen)
+               if (!isxdigit(in[0]) || !isxdigit(in[1]) || l >= maxlen)
                        return -1;
-               out[++l] = (hex2bin(in[0]) << 4) + hex2bin(in[1]);
+               out[++l] = (hex_to_bin(in[0]) << 4) + hex_to_bin(in[1]);
                in += 2;
        }
        out[0] = l;
@@ -362,6 +338,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
        struct cardstate *cs = bcs->cs;
        struct gigaset_capi_ctr *iif = cs->iif;
        struct gigaset_capi_appl *ap = bcs->ap;
+       unsigned char *req = skb_mac_header(dskb);
        struct sk_buff *cskb;
        u16 flags;
 
@@ -380,7 +357,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
        }
 
        /* ToDo: honor unset "delivery confirmation" bit */
-       flags = CAPIMSG_FLAGS(dskb->head);
+       flags = CAPIMSG_FLAGS(req);
 
        /* build DATA_B3_CONF message */
        cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
@@ -393,11 +370,11 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
        CAPIMSG_SETAPPID(cskb->data, ap->id);
        CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
        CAPIMSG_SETSUBCOMMAND(cskb->data,  CAPI_CONF);
-       CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(dskb->head));
+       CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
        CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
        CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
        CAPIMSG_SETNCCI_PART(cskb->data, 1);
-       CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(dskb->head));
+       CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
        if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
                CAPIMSG_SETINFO_CONF(cskb->data,
                                     CapiFlagsNotSupportedByProtocol);
@@ -437,7 +414,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
        /* don't send further B3 messages if disconnected */
        if (ap->connected < APCONN_ACTIVE) {
                gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return;
        }
 
@@ -1312,7 +1289,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
        }
 
        /* check parameter: CIP Value */
-       if (cmsg->CIPValue > ARRAY_SIZE(cip2bchlc) ||
+       if (cmsg->CIPValue >= ARRAY_SIZE(cip2bchlc) ||
            (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) {
                dev_notice(cs->dev, "%s: unknown CIP value %d\n",
                           "CONNECT_REQ", cmsg->CIPValue);
@@ -1424,9 +1401,10 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
 
        /* queue & schedule EV_DIAL event */
        if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands,
-                              bcs->at_state.seq_index, NULL))
-               goto oom;
-       gig_dbg(DEBUG_CMD, "scheduling DIAL");
+                              bcs->at_state.seq_index, NULL)) {
+               info = CAPI_MSGOSRESOURCEERR;
+               goto error;
+       }
        gigaset_schedule_event(cs);
        ap->connected = APCONN_SETUP;
        send_conf(iif, ap, skb, CapiSuccess);
@@ -1461,7 +1439,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
        /* decode message */
        capi_message2cmsg(cmsg, skb->data);
        dump_cmsg(DEBUG_CMD, __func__, cmsg);
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 
        /* extract and check channel number from PLCI */
        channel = (cmsg->adr.adrPLCI >> 8) & 0xff;
@@ -1540,7 +1518,6 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
                if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
                                       EV_ACCEPT, NULL, 0, NULL))
                        return;
-               gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
                gigaset_schedule_event(cs);
                return;
 
@@ -1581,7 +1558,6 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
                if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
                                       EV_HUP, NULL, 0, NULL))
                        return;
-               gig_dbg(DEBUG_CMD, "scheduling HUP");
                gigaset_schedule_event(cs);
                return;
        }
@@ -1652,7 +1628,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
            ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) {
                dev_notice(cs->dev, "%s: invalid %s 0x%02x\n",
                           "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI);
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return;
        }
        bcs = &cs->bcs[channel-1];
@@ -1664,11 +1640,9 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
                /* trigger hangup, causing eventual DISCONNECT_IND */
                if (!gigaset_add_event(cs, &bcs->at_state,
                                       EV_HUP, NULL, 0, NULL)) {
-                       dev_err(cs->dev, "%s: out of memory\n", __func__);
-                       dev_kfree_skb(skb);
+                       dev_kfree_skb_any(skb);
                        return;
                }
-               gig_dbg(DEBUG_CMD, "scheduling HUP");
                gigaset_schedule_event(cs);
 
                /* emit DISCONNECT_B3_IND */
@@ -1767,11 +1741,9 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
 
        /* trigger hangup, causing eventual DISCONNECT_IND */
        if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
-               dev_err(cs->dev, "%s: out of memory\n", __func__);
                send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
                return;
        }
-       gig_dbg(DEBUG_CMD, "scheduling HUP");
        gigaset_schedule_event(cs);
 
        /* emit reply */
@@ -1814,11 +1786,9 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
        /* trigger hangup, causing eventual DISCONNECT_B3_IND */
        if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
                               EV_HUP, NULL, 0, NULL)) {
-               dev_err(cs->dev, "%s: out of memory\n", __func__);
                send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
                return;
        }
-       gig_dbg(DEBUG_CMD, "scheduling HUP");
        gigaset_schedule_event(cs);
 
        /* NCPI parameter: not applicable for B3 Transparent */
@@ -1880,12 +1850,12 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
                return;
        }
 
-       /*
-        * pull CAPI message from skb,
-        * pass payload data to device-specific module
-        * CAPI message will be preserved in headroom
-        */
+       /* pull CAPI message into link layer header */
+       skb_reset_mac_header(skb);
+       skb->mac_len = msglen;
        skb_pull(skb, msglen);
+
+       /* pass to device-specific module */
        if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) {
                send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
                return;
@@ -1946,7 +1916,7 @@ static void do_nothing(struct gigaset_capi_ctr *iif,
                capi_message2cmsg(&iif->acmsg, skb->data);
                dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
        }
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 }
 
 static void do_data_b3_resp(struct gigaset_capi_ctr *iif,
@@ -1954,7 +1924,7 @@ static void do_data_b3_resp(struct gigaset_capi_ctr *iif,
                            struct sk_buff *skb)
 {
        dump_rawmsg(DEBUG_LLDATA, __func__, skb->data);
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 }
 
 /* table of outgoing CAPI message handlers with lookup function */
@@ -2105,35 +2075,22 @@ static char *gigaset_procinfo(struct capi_ctr *ctr)
        return ctr->name;       /* ToDo: more? */
 }
 
-/**
- * gigaset_ctr_read_proc() - build controller proc file entry
- * @page:      buffer of PAGE_SIZE bytes for receiving the entry.
- * @start:     unused.
- * @off:       unused.
- * @count:     unused.
- * @eof:       unused.
- * @ctr:       controller descriptor structure.
- *
- * Return value: length of generated entry
- */
-static int gigaset_ctr_read_proc(char *page, char **start, off_t off,
-                         int count, int *eof, struct capi_ctr *ctr)
+static int gigaset_proc_show(struct seq_file *m, void *v)
 {
+       struct capi_ctr *ctr = m->private;
        struct cardstate *cs = ctr->driverdata;
        char *s;
        int i;
-       int len = 0;
-       len += sprintf(page+len, "%-16s %s\n", "name", ctr->name);
-       len += sprintf(page+len, "%-16s %s %s\n", "dev",
+
+       seq_printf(m, "%-16s %s\n", "name", ctr->name);
+       seq_printf(m, "%-16s %s %s\n", "dev",
                        dev_driver_string(cs->dev), dev_name(cs->dev));
-       len += sprintf(page+len, "%-16s %d\n", "id", cs->myid);
+       seq_printf(m, "%-16s %d\n", "id", cs->myid);
        if (cs->gotfwver)
-               len += sprintf(page+len, "%-16s %d.%d.%d.%d\n", "firmware",
+               seq_printf(m, "%-16s %d.%d.%d.%d\n", "firmware",
                        cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]);
-       len += sprintf(page+len, "%-16s %d\n", "channels",
-                       cs->channels);
-       len += sprintf(page+len, "%-16s %s\n", "onechannel",
-                       cs->onechannel ? "yes" : "no");
+       seq_printf(m, "%-16s %d\n", "channels", cs->channels);
+       seq_printf(m, "%-16s %s\n", "onechannel", cs->onechannel ? "yes" : "no");
 
        switch (cs->mode) {
        case M_UNKNOWN:
@@ -2151,7 +2108,7 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off,
        default:
                s = "??";
        }
-       len += sprintf(page+len, "%-16s %s\n", "mode", s);
+       seq_printf(m, "%-16s %s\n", "mode", s);
 
        switch (cs->mstate) {
        case MS_UNINITIALIZED:
@@ -2175,25 +2132,21 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off,
        default:
                s = "??";
        }
-       len += sprintf(page+len, "%-16s %s\n", "mstate", s);
+       seq_printf(m, "%-16s %s\n", "mstate", s);
 
-       len += sprintf(page+len, "%-16s %s\n", "running",
-                       cs->running ? "yes" : "no");
-       len += sprintf(page+len, "%-16s %s\n", "connected",
-                       cs->connected ? "yes" : "no");
-       len += sprintf(page+len, "%-16s %s\n", "isdn_up",
-                       cs->isdn_up ? "yes" : "no");
-       len += sprintf(page+len, "%-16s %s\n", "cidmode",
-                       cs->cidmode ? "yes" : "no");
+       seq_printf(m, "%-16s %s\n", "running", cs->running ? "yes" : "no");
+       seq_printf(m, "%-16s %s\n", "connected", cs->connected ? "yes" : "no");
+       seq_printf(m, "%-16s %s\n", "isdn_up", cs->isdn_up ? "yes" : "no");
+       seq_printf(m, "%-16s %s\n", "cidmode", cs->cidmode ? "yes" : "no");
 
        for (i = 0; i < cs->channels; i++) {
-               len += sprintf(page+len, "[%d]%-13s %d\n", i, "corrupted",
+               seq_printf(m, "[%d]%-13s %d\n", i, "corrupted",
                                cs->bcs[i].corrupted);
-               len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_down",
+               seq_printf(m, "[%d]%-13s %d\n", i, "trans_down",
                                cs->bcs[i].trans_down);
-               len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_up",
+               seq_printf(m, "[%d]%-13s %d\n", i, "trans_up",
                                cs->bcs[i].trans_up);
-               len += sprintf(page+len, "[%d]%-13s %d\n", i, "chstate",
+               seq_printf(m, "[%d]%-13s %d\n", i, "chstate",
                                cs->bcs[i].chstate);
                switch (cs->bcs[i].proto2) {
                case L2_BITSYNC:
@@ -2208,42 +2161,42 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off,
                default:
                        s = "??";
                }
-               len += sprintf(page+len, "[%d]%-13s %s\n", i, "proto2", s);
+               seq_printf(m, "[%d]%-13s %s\n", i, "proto2", s);
        }
-       return len;
+       return 0;
 }
 
+static int gigaset_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, gigaset_proc_show, PDE(inode)->data);
+}
 
-static struct capi_driver capi_driver_gigaset = {
-       .name           = "gigaset",
-       .revision       = "1.0",
+static const struct file_operations gigaset_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = gigaset_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
 };
 
 /**
- * gigaset_isdn_register() - register to LL
+ * gigaset_isdn_regdev() - register device to LL
  * @cs:                device descriptor structure.
  * @isdnid:    device name.
  *
- * Called by main module to register the device with the LL.
- *
  * Return value: 1 for success, 0 for failure
  */
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
 {
        struct gigaset_capi_ctr *iif;
        int rc;
 
-       pr_info("Kernel CAPI interface\n");
-
        iif = kmalloc(sizeof(*iif), GFP_KERNEL);
        if (!iif) {
                pr_err("%s: out of memory\n", __func__);
                return 0;
        }
 
-       /* register driver with CAPI (ToDo: what for?) */
-       register_capi_driver(&capi_driver_gigaset);
-
        /* prepare controller structure */
        iif->ctr.owner         = THIS_MODULE;
        iif->ctr.driverdata    = cs;
@@ -2255,7 +2208,7 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
        iif->ctr.release_appl  = gigaset_release_appl;
        iif->ctr.send_message  = gigaset_send_message;
        iif->ctr.procinfo      = gigaset_procinfo;
-       iif->ctr.ctr_read_proc = gigaset_ctr_read_proc;
+       iif->ctr.proc_fops = &gigaset_proc_fops;
        INIT_LIST_HEAD(&iif->appls);
        skb_queue_head_init(&iif->sendqueue);
        atomic_set(&iif->sendqlen, 0);
@@ -2264,7 +2217,6 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
        rc = attach_capi_ctr(&iif->ctr);
        if (rc) {
                pr_err("attach_capi_ctr failed (%d)\n", rc);
-               unregister_capi_driver(&capi_driver_gigaset);
                kfree(iif);
                return 0;
        }
@@ -2275,17 +2227,36 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
 }
 
 /**
- * gigaset_isdn_unregister() - unregister from LL
+ * gigaset_isdn_unregdev() - unregister device from LL
  * @cs:                device descriptor structure.
- *
- * Called by main module to unregister the device from the LL.
  */
-void gigaset_isdn_unregister(struct cardstate *cs)
+void gigaset_isdn_unregdev(struct cardstate *cs)
 {
        struct gigaset_capi_ctr *iif = cs->iif;
 
        detach_capi_ctr(&iif->ctr);
        kfree(iif);
        cs->iif = NULL;
+}
+
+static struct capi_driver capi_driver_gigaset = {
+       .name           = "gigaset",
+       .revision       = "1.0",
+};
+
+/**
+ * gigaset_isdn_regdrv() - register driver to LL
+ */
+void gigaset_isdn_regdrv(void)
+{
+       pr_info("Kernel CAPI interface\n");
+       register_capi_driver(&capi_driver_gigaset);
+}
+
+/**
+ * gigaset_isdn_unregdrv() - unregister driver from LL
+ */
+void gigaset_isdn_unregdrv(void)
+{
        unregister_capi_driver(&capi_driver_gigaset);
 }