From 088ec0cc96e2befd5f3c035123f95c17bdf26e64 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 6 Oct 2009 12:19:07 +0000 Subject: gigaset: prepare for CAPI implementation Reorganize the code of the Gigaset driver, moving all isdn4linux dependencies to the source file i4l.c so that it can be replaced by a file capi.c interfacing to Kernel CAPI instead. Impact: refactoring, no functional change Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 124 +++++---- drivers/isdn/gigaset/bas-gigaset.c | 4 +- drivers/isdn/gigaset/common.c | 50 ++-- drivers/isdn/gigaset/ev-layer.c | 64 +++-- drivers/isdn/gigaset/gigaset.h | 90 ++----- drivers/isdn/gigaset/i4l.c | 506 ++++++++++++++++++++++--------------- drivers/isdn/gigaset/isocdata.c | 79 +++--- 7 files changed, 492 insertions(+), 425 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 44a58e6f8f65..a25216bf475e 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -119,10 +119,7 @@ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, int inputstate = bcs->inputstate; __u16 fcs = bcs->fcs; struct sk_buff *skb = bcs->skb; - unsigned char error; - struct sk_buff *compskb; int startbytes = numbytes; - int l; if (unlikely(inputstate & INS_byte_stuff)) { inputstate &= ~INS_byte_stuff; @@ -158,8 +155,8 @@ byte_stuff: #endif /* end of frame */ - error = 1; - gigaset_rcv_error(NULL, cs, bcs); + gigaset_isdn_rcv_err(bcs); + dev_kfree_skb(skb); } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ #ifdef CONFIG_GIGASET_DEBUG ++bcs->emptycount; @@ -170,54 +167,39 @@ byte_stuff: "7e----------------------------"); /* end of frame */ - error = 0; - if (unlikely(fcs != PPP_GOODFCS)) { dev_err(cs->dev, "Checksum failed, %u bytes corrupted!\n", skb->len); - compskb = NULL; - gigaset_rcv_error(compskb, cs, bcs); - error = 1; + gigaset_isdn_rcv_err(bcs); + dev_kfree_skb(skb); + } else if (likely(skb->len > 2)) { + __skb_trim(skb, skb->len - 2); + gigaset_skb_rcvd(bcs, skb); } else { - if (likely((l = skb->len) > 2)) { - skb->tail -= 2; - skb->len -= 2; - } else { - dev_kfree_skb(skb); - skb = NULL; - inputstate |= INS_skip_frame; - if (l == 1) { - dev_err(cs->dev, - "invalid packet size (1)!\n"); - error = 1; - gigaset_rcv_error(NULL, - cs, bcs); - } - } - if (likely(!(error || - (inputstate & - INS_skip_frame)))) { - gigaset_rcv_skb(skb, cs, bcs); + if (skb->len) { + dev_err(cs->dev, + "invalid packet size (%d)\n", skb->len); + gigaset_isdn_rcv_err(bcs); } + dev_kfree_skb(skb); } } - if (unlikely(error)) - if (skb) - dev_kfree_skb(skb); - fcs = PPP_INITFCS; inputstate &= ~(INS_have_data | INS_skip_frame); if (unlikely(bcs->ignore)) { inputstate |= INS_skip_frame; skb = NULL; - } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) { - skb_reserve(skb, HW_HDR_LEN); } else { - dev_warn(cs->dev, - "could not allocate new skb\n"); - inputstate |= INS_skip_frame; + skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); + if (skb != NULL) { + skb_reserve(skb, cs->hw_hdr_len); + } else { + dev_warn(cs->dev, + "could not allocate new skb\n"); + inputstate |= INS_skip_frame; + } } break; @@ -314,18 +296,21 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, /* pass data up */ if (likely(inputstate & INS_have_data)) { if (likely(!(inputstate & INS_skip_frame))) { - gigaset_rcv_skb(skb, cs, bcs); + gigaset_skb_rcvd(bcs, skb); } inputstate &= ~(INS_have_data | INS_skip_frame); if (unlikely(bcs->ignore)) { inputstate |= INS_skip_frame; skb = NULL; - } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) - != NULL)) { - skb_reserve(skb, HW_HDR_LEN); } else { - dev_warn(cs->dev, "could not allocate new skb\n"); - inputstate |= INS_skip_frame; + skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); + if (skb != NULL) { + skb_reserve(skb, cs->hw_hdr_len); + } else { + dev_warn(cs->dev, + "could not allocate new skb\n"); + inputstate |= INS_skip_frame; + } } } @@ -383,7 +368,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) /* FIXME use function pointers? */ if (inbuf->inputstate & INS_command) procbytes = cmd_loop(c, src, numbytes, inbuf); - else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC) + else if (inbuf->bcs->proto2 == L2_HDLC) procbytes = hdlc_loop(c, src, numbytes, inbuf); else procbytes = iraw_loop(c, src, numbytes, inbuf); @@ -440,16 +425,16 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input); /* == data output ========================================================== */ -/* Encoding of a PPP packet into an octet stuffed HDLC frame - * with FCS, opening and closing flags. +/* + * Encode a data packet into an octet stuffed HDLC frame with FCS, + * opening and closing flags, preserving headroom data. * parameters: - * skb skb containing original packet (freed upon return) - * head number of headroom bytes to allocate in result skb - * tail number of tailroom bytes to allocate in result skb + * skb skb containing original packet (freed upon return) + * headroom number of headroom bytes to preserve * Return value: * pointer to newly allocated skb containing the result frame */ -static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) +static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) { struct sk_buff *hdlc_skb; __u16 fcs; @@ -471,16 +456,17 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) /* size of new buffer: original size + number of stuffing bytes * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes + * + room for acknowledgement header */ - hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head); + hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + headroom); if (!hdlc_skb) { dev_kfree_skb(skb); return NULL; } - skb_reserve(hdlc_skb, head); - /* Copy acknowledge request into new skb */ - memcpy(hdlc_skb->head, skb->head, 2); + /* Copy acknowledgement header into new skb */ + skb_reserve(hdlc_skb, headroom); + memcpy(hdlc_skb->head, skb->head, headroom); /* Add flag sequence in front of everything.. */ *(skb_put(hdlc_skb, 1)) = PPP_FLAG; @@ -515,15 +501,16 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) return hdlc_skb; } -/* Encoding of a raw packet into an octet stuffed bit inverted frame +/* + * Encode a data packet into an octet stuffed raw bit inverted frame, + * preserving headroom data. * parameters: - * skb skb containing original packet (freed upon return) - * head number of headroom bytes to allocate in result skb - * tail number of tailroom bytes to allocate in result skb + * skb skb containing original packet (freed upon return) + * headroom number of headroom bytes to preserve * Return value: * pointer to newly allocated skb containing the result frame */ -static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) +static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) { struct sk_buff *iraw_skb; unsigned char c; @@ -531,12 +518,15 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) int len; /* worst case: every byte must be stuffed */ - iraw_skb = dev_alloc_skb(2*skb->len + tail + head); + iraw_skb = dev_alloc_skb(2*skb->len + headroom); if (!iraw_skb) { dev_kfree_skb(skb); return NULL; } - skb_reserve(iraw_skb, head); + + /* Copy acknowledgement header into new skb */ + skb_reserve(iraw_skb, headroom); + memcpy(iraw_skb->head, skb->head, headroom); cp = skb->data; len = skb->len; @@ -555,8 +545,10 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) * @bcs: B channel descriptor structure. * @skb: data to send. * - * Called by i4l.c to encode and queue an skb for sending, and start + * Called by LL to encode and queue an skb for sending, and start * transmission if necessary. + * Once the payload data has been transmitted completely, gigaset_skb_sent() + * will be called with the first cs->hw_hdr_len bytes of skb->head preserved. * * Return value: * number of bytes accepted for sending (skb->len) if ok, @@ -567,10 +559,10 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) unsigned len = skb->len; unsigned long flags; - if (bcs->proto2 == ISDN_PROTO_L2_HDLC) - skb = HDLC_Encode(skb, HW_HDR_LEN, 0); + if (bcs->proto2 == L2_HDLC) + skb = HDLC_Encode(skb, bcs->cs->hw_hdr_len); else - skb = iraw_encode(skb, HW_HDR_LEN, 0); + skb = iraw_encode(skb, bcs->cs->hw_hdr_len); if (!skb) { dev_err(bcs->cs->dev, "unable to allocate memory for encoding!\n"); diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 5ed1d99eb9f3..388e63a8ae94 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -911,7 +911,7 @@ static int starturbs(struct bc_state *bcs) int rc; /* initialize L2 reception */ - if (bcs->proto2 == ISDN_PROTO_L2_HDLC) + if (bcs->proto2 == L2_HDLC) bcs->inputstate |= INS_flag_hunt; /* submit all isochronous input URBs */ @@ -1064,7 +1064,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) "%s: buffer busy at frame %d", __func__, nframe); /* tasklet will be restarted from - gigaset_send_skb() */ + gigaset_isoc_send_skb() */ } else { dev_err(ucx->bcs->cs->dev, "%s: buffer error %d at frame %d\n", diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 33dcd8d72b7c..15dc0fc28a96 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -463,6 +463,12 @@ void gigaset_freecs(struct cardstate *cs) switch (cs->cs_init) { default: + /* clear B channel structures */ + for (i = 0; i < cs->channels; ++i) { + gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); + gigaset_freebcs(cs->bcs + i); + } + /* clear device sysfs */ gigaset_free_dev_sysfs(cs); @@ -477,22 +483,16 @@ void gigaset_freecs(struct cardstate *cs) case 2: /* error in initcshw */ /* Deregister from LL */ make_invalid(cs, VALID_ID); - gig_dbg(DEBUG_INIT, "clearing iif"); - gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); + gigaset_isdn_unregister(cs); /* fall through */ - case 1: /* error when regestering to LL */ + case 1: /* error when registering to LL */ gig_dbg(DEBUG_INIT, "clearing at_state"); clear_at_state(&cs->at_state); dealloc_at_states(cs); /* fall through */ - case 0: /* error in one call to initbcs */ - for (i = 0; i < cs->channels; ++i) { - gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); - gigaset_freebcs(cs->bcs + i); - } - + case 0: /* error in basic setup */ clear_events(cs); gig_dbg(DEBUG_INIT, "freeing inbuf"); kfree(cs->inbuf); @@ -620,11 +620,14 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, if (cs->ignoreframes) { bcs->inputstate |= INS_skip_frame; bcs->skb = NULL; - } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) - skb_reserve(bcs->skb, HW_HDR_LEN); - else { - pr_err("out of memory\n"); - bcs->inputstate |= INS_skip_frame; + } else { + bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); + if (bcs->skb != NULL) + skb_reserve(bcs->skb, cs->hw_hdr_len); + else { + pr_err("out of memory\n"); + bcs->inputstate |= INS_skip_frame; + } } bcs->channel = channel; @@ -726,14 +729,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->mode = M_UNKNOWN; cs->mstate = MS_UNINITIALIZED; - for (i = 0; i < channels; ++i) { - gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); - if (!gigaset_initbcs(cs->bcs + i, cs, i)) { - pr_err("could not allocate channel %d data\n", i); - goto error; - } - } - ++cs->cs_init; gig_dbg(DEBUG_INIT, "setting up at_state"); @@ -758,7 +753,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->cmdbytes = 0; gig_dbg(DEBUG_INIT, "setting up iif"); - if (!gigaset_register_to_LL(cs, modulename)) { + if (!gigaset_isdn_register(cs, modulename)) { pr_err("error registering ISDN device\n"); goto error; } @@ -777,6 +772,15 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, /* set up device sysfs */ gigaset_init_dev_sysfs(cs); + /* set up channel data structures */ + for (i = 0; i < channels; ++i) { + gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i); + if (!gigaset_initbcs(cs->bcs + i, cs, i)) { + pr_err("could not allocate channel %d data\n", i); + goto error; + } + } + spin_lock_irqsave(&cs->lock, flags); cs->running = 1; spin_unlock_irqrestore(&cs->lock, flags); diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cc768caa38f5..cb25d2b834b9 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -127,7 +127,6 @@ #define ACT_NOTIFY_BC_UP 39 #define ACT_DIAL 40 #define ACT_ACCEPT 41 -#define ACT_PROTO_L2 42 #define ACT_HUP 43 #define ACT_IF_LOCK 44 #define ACT_START 45 @@ -365,8 +364,6 @@ struct reply_t gigaset_tab_cid[] = {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME /* misc. */ - {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME - {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME @@ -714,7 +711,7 @@ static void disconnect(struct at_state_t **at_state_p) /* notify LL */ if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); + gigaset_isdn_hupD(bcs); } } else { /* no B channel assigned: just deallocate */ @@ -872,12 +869,12 @@ static void bchannel_down(struct bc_state *bcs) { if (bcs->chstate & CHS_B_UP) { bcs->chstate &= ~CHS_B_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); + gigaset_isdn_hupB(bcs); } if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); + gigaset_isdn_hupD(bcs); } gigaset_free_channel(bcs); @@ -894,15 +891,16 @@ static void bchannel_up(struct bc_state *bcs) } bcs->chstate |= CHS_B_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); + gigaset_isdn_connB(bcs); } static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) { struct bc_state *bcs = at_state->bcs; struct cardstate *cs = at_state->cs; - int retval; + char **commands = data; unsigned long flags; + int i; bcs->chstate |= CHS_NOTIFY_LL; @@ -913,10 +911,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind } spin_unlock_irqrestore(&cs->lock, flags); - retval = gigaset_isdn_setup_dial(at_state, data); - if (retval != 0) - goto error; - + for (i = 0; i < AT_NUM; ++i) { + kfree(bcs->commands[i]); + bcs->commands[i] = commands[i]; + } at_state->pending_commands |= PC_CID; gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); @@ -924,6 +922,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind return; error: + for (i = 0; i < AT_NUM; ++i) { + kfree(commands[i]); + commands[i] = NULL; + } at_state->pending_commands |= PC_NOCID; gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); cs->commands_pending = 1; @@ -933,20 +935,31 @@ error: static void start_accept(struct at_state_t *at_state) { struct cardstate *cs = at_state->cs; - int retval; + struct bc_state *bcs = at_state->bcs; + int i; - retval = gigaset_isdn_setup_accept(at_state); + for (i = 0; i < AT_NUM; ++i) { + kfree(bcs->commands[i]); + bcs->commands[i] = NULL; + } - if (retval == 0) { - at_state->pending_commands |= PC_ACCEPT; - gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); - cs->commands_pending = 1; - } else { + bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); + bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); + if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) { + dev_err(at_state->cs->dev, "out of memory\n"); /* error reset */ at_state->pending_commands |= PC_HUP; gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); cs->commands_pending = 1; + return; } + + snprintf(bcs->commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); + snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); + + at_state->pending_commands |= PC_ACCEPT; + gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); + cs->commands_pending = 1; } static void do_start(struct cardstate *cs) @@ -957,7 +970,7 @@ static void do_start(struct cardstate *cs) schedule_init(cs, MS_INIT); cs->isdn_up = 1; - gigaset_i4l_cmd(cs, ISDN_STAT_RUN); + gigaset_isdn_start(cs); // FIXME: not in locked mode // FIXME 2: only after init sequence @@ -975,7 +988,7 @@ static void finish_shutdown(struct cardstate *cs) /* Tell the LL that the device is not available .. */ if (cs->isdn_up) { cs->isdn_up = 0; - gigaset_i4l_cmd(cs, ISDN_STAT_STOP); + gigaset_isdn_stop(cs); } /* The rest is done by cleanup_cs () in user mode. */ @@ -1276,7 +1289,7 @@ static void do_action(int action, struct cardstate *cs, break; } bcs->chstate |= CHS_D_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); + gigaset_isdn_connD(bcs); cs->ops->init_bchannel(bcs); break; case ACT_DLE1: @@ -1284,7 +1297,7 @@ static void do_action(int action, struct cardstate *cs, bcs = cs->bcs + cs->curchannel; bcs->chstate |= CHS_D_UP; - gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); + gigaset_isdn_connD(bcs); cs->ops->init_bchannel(bcs); break; case ACT_FAKEHUP: @@ -1474,11 +1487,6 @@ static void do_action(int action, struct cardstate *cs, case ACT_ACCEPT: start_accept(at_state); break; - case ACT_PROTO_L2: - gig_dbg(DEBUG_CMD, "set protocol to %u", - (unsigned) ev->parameter); - at_state->bcs->proto2 = ev->parameter; - break; case ACT_HUP: at_state->pending_commands |= PC_HUP; cs->commands_pending = 1; diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index a2f6125739eb..1185da2dbf61 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,6 @@ #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ #define MAX_RESP_SIZE 512 /* Max. size of a response string */ -#define HW_HDR_LEN 2 /* Header size used to store ack info */ #define MAX_EVENTS 64 /* size of event queue */ @@ -216,7 +214,6 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define EV_START -110 #define EV_STOP -111 #define EV_IF_LOCK -112 -#define EV_PROTO_L2 -113 #define EV_ACCEPT -114 #define EV_DIAL -115 #define EV_HUP -116 @@ -259,6 +256,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define SM_LOCKED 0 #define SM_ISDN 1 /* default */ +/* layer 2 protocols (AT^SBPR=...) */ +#define L2_BITSYNC 0 +#define L2_HDLC 1 +#define L2_VOICE 2 + struct gigaset_ops; struct gigaset_driver; @@ -395,7 +397,7 @@ struct bc_state { unsigned chstate; /* bitmap (CHS_*) */ int ignore; - unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ + unsigned proto2; /* layer 2 protocol (L2_*) */ char *commands[AT_NUM]; /* see AT_XXXX */ #ifdef CONFIG_GIGASET_DEBUG @@ -456,12 +458,13 @@ struct cardstate { unsigned running; /* !=0 if events are handled */ unsigned connected; /* !=0 if hardware is connected */ - unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */ + unsigned isdn_up; /* !=0 after gigaset_isdn_start() */ unsigned cidmode; int myid; /* id for communication with LL */ - isdn_if iif; + void *iif; /* LL interface structure */ + unsigned short hw_hdr_len; /* headroom needed in data skbs */ struct reply_t *tabnocid; struct reply_t *tabcid; @@ -616,7 +619,9 @@ struct gigaset_ops { int (*baud_rate)(struct cardstate *cs, unsigned cflag); int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); - /* Called from i4l.c to put an skb into the send-queue. */ + /* Called from LL interface to put an skb into the send-queue. + * After sending is completed, gigaset_skb_sent() must be called + * with the first cs->hw_hdr_len bytes of skb->head preserved. */ int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data @@ -638,8 +643,7 @@ struct gigaset_ops { * Functions implemented in asyncdata.c */ -/* Called from i4l.c to put an skb into the send-queue. - * After sending gigaset_skb_sent() should be called. */ +/* Called from LL interface to put an skb into the send queue. */ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data @@ -650,8 +654,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf); * Functions implemented in isocdata.c */ -/* Called from i4l.c to put an skb into the send-queue. - * After sending gigaset_skb_sent() should be called. */ +/* Called from LL interface to put an skb into the send queue. */ int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data @@ -674,36 +677,26 @@ void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle); int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); /* =========================================================================== - * Functions implemented in i4l.c/gigaset.h + * Functions implemented in LL interface */ -/* Called by gigaset_initcs() for setting up with the isdn4linux subsystem */ -int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid); +/* Called from common.c for setting up/shutting down with the ISDN subsystem */ +int gigaset_isdn_register(struct cardstate *cs, const char *isdnid); +void gigaset_isdn_unregister(struct cardstate *cs); -/* Called from xxx-gigaset.c to indicate completion of sending an skb */ +/* Called from hardware module to indicate completion of an skb */ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb); +void gigaset_isdn_rcv_err(struct bc_state *bcs); /* Called from common.c/ev-layer.c to indicate events relevant to the LL */ +void gigaset_isdn_start(struct cardstate *cs); +void gigaset_isdn_stop(struct cardstate *cs); int gigaset_isdn_icall(struct at_state_t *at_state); -int gigaset_isdn_setup_accept(struct at_state_t *at_state); -int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data); - -void gigaset_i4l_cmd(struct cardstate *cs, int cmd); -void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd); - - -static inline void gigaset_isdn_rcv_err(struct bc_state *bcs) -{ - isdn_ctrl response; - - /* error -> LL */ - gig_dbg(DEBUG_CMD, "sending L1ERR"); - response.driver = bcs->cs->myid; - response.command = ISDN_STAT_L1ERR; - response.arg = bcs->channel; - response.parm.errcode = ISDN_STAT_L1ERR_RECV; - bcs->cs->iif.statcallb(&response); -} +void gigaset_isdn_connD(struct bc_state *bcs); +void gigaset_isdn_hupD(struct bc_state *bcs); +void gigaset_isdn_connB(struct bc_state *bcs); +void gigaset_isdn_hupB(struct bc_state *bcs); /* =========================================================================== * Functions implemented in ev-layer.c @@ -816,35 +809,6 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) /* handling routines for sk_buff */ /* ============================= */ -/* pass received skb to LL - * Warning: skb must not be accessed anymore! - */ -static inline void gigaset_rcv_skb(struct sk_buff *skb, - struct cardstate *cs, - struct bc_state *bcs) -{ - cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb); - bcs->trans_down++; -} - -/* handle reception of corrupted skb - * Warning: skb must not be accessed anymore! - */ -static inline void gigaset_rcv_error(struct sk_buff *procskb, - struct cardstate *cs, - struct bc_state *bcs) -{ - if (procskb) - dev_kfree_skb(procskb); - - if (bcs->ignore) - --bcs->ignore; - else { - ++bcs->corrupted; - gigaset_isdn_rcv_err(bcs); - } -} - /* append received bytes to inbuf */ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, unsigned numbytes); diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 654489d836cd..aca72a06184e 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -14,6 +14,9 @@ */ #include "gigaset.h" +#include + +#define HW_HDR_LEN 2 /* Header size used to store ack info */ /* == Handling of I4L IO =====================================================*/ @@ -95,6 +98,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack, */ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) { + isdn_if *iif = bcs->cs->iif; unsigned len; isdn_ctrl response; @@ -114,71 +118,177 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) response.command = ISDN_STAT_BSENT; response.arg = bcs->channel; response.parm.length = len; - bcs->cs->iif.statcallb(&response); + iif->statcallb(&response); } } EXPORT_SYMBOL_GPL(gigaset_skb_sent); +/** + * gigaset_skb_rcvd() - pass received skb to LL + * @bcs: B channel descriptor structure. + * @skb: received data. + * + * Called by hardware module {bas,ser,usb}_gigaset when user data has + * been successfully received, for passing to the LL. + * Warning: skb must not be accessed anymore! + */ +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) +{ + isdn_if *iif = bcs->cs->iif; + + iif->rcvcallb_skb(bcs->cs->myid, bcs->channel, skb); + bcs->trans_down++; +} +EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); + +/** + * gigaset_isdn_rcv_err() - signal receive error + * @bcs: B channel descriptor structure. + * + * Called by hardware module {bas,ser,usb}_gigaset when a receive error + * has occurred, for signalling to the LL. + */ +void gigaset_isdn_rcv_err(struct bc_state *bcs) +{ + isdn_if *iif = bcs->cs->iif; + isdn_ctrl response; + + /* if currently ignoring packets, just count down */ + if (bcs->ignore) { + bcs->ignore--; + return; + } + + /* update statistics */ + bcs->corrupted++; + + /* error -> LL */ + gig_dbg(DEBUG_CMD, "sending L1ERR"); + response.driver = bcs->cs->myid; + response.command = ISDN_STAT_L1ERR; + response.arg = bcs->channel; + response.parm.errcode = ISDN_STAT_L1ERR_RECV; + iif->statcallb(&response); +} +EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); + /* This function will be called by LL to send commands * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, * so don't put too much effort into it. */ static int command_from_LL(isdn_ctrl *cntrl) { - struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver); + struct cardstate *cs; struct bc_state *bcs; int retval = 0; - struct setup_parm *sp; + char **commands; + int ch; + int i; + size_t l; gigaset_debugdrivers(); - if (!cs) { + gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx", + cntrl->driver, cntrl->command, cntrl->arg); + + cs = gigaset_get_cs_by_id(cntrl->driver); + if (cs == NULL) { pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver); return -ENODEV; } + ch = cntrl->arg & 0xff; switch (cntrl->command) { case ISDN_CMD_IOCTL: - gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)", - cntrl->driver, cntrl->arg); - dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n"); return -EINVAL; case ISDN_CMD_DIAL: gig_dbg(DEBUG_ANY, - "ISDN_CMD_DIAL (driver: %d, ch: %ld, " - "phone: %s, ownmsn: %s, si1: %d, si2: %d)", - cntrl->driver, cntrl->arg, + "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)", cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, cntrl->parm.setup.si1, cntrl->parm.setup.si2); - if (cntrl->arg >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_DIAL: invalid channel (%d)\n", - (int) cntrl->arg); + "ISDN_CMD_DIAL: invalid channel (%d)\n", ch); return -EINVAL; } - - bcs = cs->bcs + cntrl->arg; - + bcs = cs->bcs + ch; if (!gigaset_get_channel(bcs)) { dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); return -EBUSY; } - sp = kmalloc(sizeof *sp, GFP_ATOMIC); - if (!sp) { + commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); + if (!commands) { gigaset_free_channel(bcs); dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); return -ENOMEM; } - *sp = cntrl->parm.setup; - if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, + l = 3 + strlen(cntrl->parm.setup.phone); + commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC); + if (!commands[AT_DIAL]) + goto oom; + if (cntrl->parm.setup.phone[0] == '*' && + cntrl->parm.setup.phone[1] == '*') { + /* internal call: translate ** prefix to CTP value */ + commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC); + if (!commands[AT_TYPE]) + goto oom; + snprintf(commands[AT_DIAL], l, + "D%s\r", cntrl->parm.setup.phone+2); + } else { + commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC); + if (!commands[AT_TYPE]) + goto oom; + snprintf(commands[AT_DIAL], l, + "D%s\r", cntrl->parm.setup.phone); + } + + l = strlen(cntrl->parm.setup.eazmsn); + if (l) { + l += 8; + commands[AT_MSN] = kmalloc(l, GFP_ATOMIC); + if (!commands[AT_MSN]) + goto oom; + snprintf(commands[AT_MSN], l, "^SMSN=%s\r", + cntrl->parm.setup.eazmsn); + } + + switch (cntrl->parm.setup.si1) { + case 1: /* audio */ + /* BC = 9090A3: 3.1 kHz audio, A-law */ + commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC); + if (!commands[AT_BC]) + goto oom; + break; + case 7: /* data */ + default: /* hope the app knows what it is doing */ + /* BC = 8890: unrestricted digital information */ + commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC); + if (!commands[AT_BC]) + goto oom; + } + /* ToDo: other si1 values, inspect si2, set HLC/LLC */ + + commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); + if (!commands[AT_PROTO]) + goto oom; + snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); + + commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); + if (!commands[AT_ISO]) + goto oom; + snprintf(commands[AT_ISO], 9, "^SISO=%u\r", + (unsigned) bcs->channel + 1); + + if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, bcs->at_state.seq_index, NULL)) { - //FIXME what should we do? - kfree(sp); + for (i = 0; i < AT_NUM; ++i) + kfree(commands[i]); + kfree(commands); gigaset_free_channel(bcs); return -ENOMEM; } @@ -186,93 +296,83 @@ static int command_from_LL(isdn_ctrl *cntrl) gig_dbg(DEBUG_CMD, "scheduling DIAL"); gigaset_schedule_event(cs); break; - case ISDN_CMD_ACCEPTD: //FIXME - gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); - - if (cntrl->arg >= cs->channels) { + case ISDN_CMD_ACCEPTD: + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", - (int) cntrl->arg); + "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch); return -EINVAL; } - - if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_ACCEPT, NULL, 0, NULL)) { - //FIXME what should we do? + bcs = cs->bcs + ch; + if (!gigaset_add_event(cs, &bcs->at_state, + EV_ACCEPT, NULL, 0, NULL)) return -ENOMEM; - } gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTB: - gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); break; case ISDN_CMD_HANGUP: - gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)", - (int) cntrl->arg); - - if (cntrl->arg >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_HANGUP: invalid channel (%d)\n", - (int) cntrl->arg); + "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch); return -EINVAL; } - - if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_HUP, NULL, 0, NULL)) { - //FIXME what should we do? + bcs = cs->bcs + ch; + if (!gigaset_add_event(cs, &bcs->at_state, + EV_HUP, NULL, 0, NULL)) return -ENOMEM; - } gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); break; - case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME - gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); + case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ + dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n"); break; - case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME - gig_dbg(DEBUG_ANY, - "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)", - cntrl->driver, cntrl->arg, cntrl->parm.num); + case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ + dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n", + cntrl->parm.num); break; case ISDN_CMD_SETL2: /* Set L2 to given protocol */ - gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); - - if ((cntrl->arg & 0xff) >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_SETL2: invalid channel (%d)\n", - (int) cntrl->arg & 0xff); + "ISDN_CMD_SETL2: invalid channel (%d)\n", ch); return -EINVAL; } - - if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, - EV_PROTO_L2, NULL, cntrl->arg >> 8, - NULL)) { - //FIXME what should we do? - return -ENOMEM; + bcs = cs->bcs + ch; + if (bcs->chstate & CHS_D_UP) { + dev_err(cs->dev, + "ISDN_CMD_SETL2: channel active (%d)\n", ch); + return -EINVAL; + } + switch (cntrl->arg >> 8) { + case ISDN_PROTO_L2_HDLC: + gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC"); + bcs->proto2 = L2_HDLC; + break; + case ISDN_PROTO_L2_TRANS: + gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE"); + bcs->proto2 = L2_VOICE; + break; + default: + dev_err(cs->dev, + "ISDN_CMD_SETL2: unsupported protocol (%lu)\n", + cntrl->arg >> 8); + return -EINVAL; } - - gig_dbg(DEBUG_CMD, "scheduling PROTO_L2"); - gigaset_schedule_event(cs); break; case ISDN_CMD_SETL3: /* Set L3 to given protocol */ - gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); - - if ((cntrl->arg & 0xff) >= cs->channels) { + if (ch >= cs->channels) { dev_err(cs->dev, - "ISDN_CMD_SETL3: invalid channel (%d)\n", - (int) cntrl->arg & 0xff); + "ISDN_CMD_SETL3: invalid channel (%d)\n", ch); return -EINVAL; } if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { dev_err(cs->dev, - "ISDN_CMD_SETL3: invalid protocol %lu\n", + "ISDN_CMD_SETL3: unsupported protocol (%lu)\n", cntrl->arg >> 8); return -EINVAL; } @@ -324,149 +424,34 @@ static int command_from_LL(isdn_ctrl *cntrl) } return retval; + +oom: + dev_err(bcs->cs->dev, "out of memory\n"); + for (i = 0; i < AT_NUM; ++i) + kfree(commands[i]); + return -ENOMEM; } -void gigaset_i4l_cmd(struct cardstate *cs, int cmd) +static void gigaset_i4l_cmd(struct cardstate *cs, int cmd) { + isdn_if *iif = cs->iif; isdn_ctrl command; command.driver = cs->myid; command.command = cmd; command.arg = 0; - cs->iif.statcallb(&command); + iif->statcallb(&command); } -void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) +static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) { + isdn_if *iif = bcs->cs->iif; isdn_ctrl command; command.driver = bcs->cs->myid; command.command = cmd; command.arg = bcs->channel; - bcs->cs->iif.statcallb(&command); -} - -int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) -{ - struct bc_state *bcs = at_state->bcs; - unsigned proto; - const char *bc; - size_t length[AT_NUM]; - size_t l; - int i; - struct setup_parm *sp = data; - - switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: - proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - case ISDN_PROTO_L2_TRANS: - proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - default: - dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n", - __func__, bcs->proto2); - return -EINVAL; - } - - switch (sp->si1) { - case 1: /* audio */ - bc = "9090A3"; /* 3.1 kHz audio, A-law */ - break; - case 7: /* data */ - default: /* hope the app knows what it is doing */ - bc = "8890"; /* unrestricted digital information */ - } - //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC - - length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1; - l = strlen(sp->eazmsn); - length[AT_MSN ] = l ? 6 + l + 1 + 1 : 0; - length[AT_BC ] = 5 + strlen(bc) + 1 + 1; - length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ - length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ - length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */ - length[AT_HLC ] = 0; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - if (length[i] && - !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - dev_err(bcs->cs->dev, "out of memory\n"); - return -ENOMEM; - } - } - - /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */ - if (sp->phone[0] == '*' && sp->phone[1] == '*') { - /* internal call: translate ** prefix to CTP value */ - snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], - "D%s\r", sp->phone+2); - strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]); - } else { - snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], - "D%s\r", sp->phone); - strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]); - } - - if (bcs->commands[AT_MSN]) - snprintf(bcs->commands[AT_MSN], length[AT_MSN], - "^SMSN=%s\r", sp->eazmsn); - snprintf(bcs->commands[AT_BC ], length[AT_BC ], - "^SBC=%s\r", bc); - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], - "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], - "^SISO=%u\r", (unsigned)bcs->channel + 1); - - return 0; -} - -int gigaset_isdn_setup_accept(struct at_state_t *at_state) -{ - unsigned proto; - size_t length[AT_NUM]; - int i; - struct bc_state *bcs = at_state->bcs; - - switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: - proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - case ISDN_PROTO_L2_TRANS: - proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ - break; - default: - dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n", - __func__, bcs->proto2); - return -EINVAL; - } - - length[AT_DIAL ] = 0; - length[AT_MSN ] = 0; - length[AT_BC ] = 0; - length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ - length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ - length[AT_TYPE ] = 0; - length[AT_HLC ] = 0; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - if (length[i] && - !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - dev_err(at_state->cs->dev, "out of memory\n"); - return -ENOMEM; - } - } - - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], - "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], - "^SISO=%u\r", (unsigned) bcs->channel + 1); - - return 0; + iif->statcallb(&command); } /** @@ -482,6 +467,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) { struct cardstate *cs = at_state->cs; struct bc_state *bcs = at_state->bcs; + isdn_if *iif = cs->iif; isdn_ctrl response; int retval; @@ -531,7 +517,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) response.arg = bcs->channel; //FIXME } response.driver = cs->myid; - retval = cs->iif.statcallb(&response); + retval = iif->statcallb(&response); gig_dbg(DEBUG_CMD, "Response: %d", retval); switch (retval) { case 0: /* no takers */ @@ -560,16 +546,109 @@ int gigaset_isdn_icall(struct at_state_t *at_state) } } -/* Set Callback function pointer */ -int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) +/** + * gigaset_isdn_connD() - signal D channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the D channel connection has + * been established. + */ +void gigaset_isdn_connD(struct bc_state *bcs) { - isdn_if *iif = &cs->iif; + gig_dbg(DEBUG_CMD, "sending DCONN"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); +} - gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); +/** + * gigaset_isdn_hupD() - signal D channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the D channel connection has + * been shut down. + */ +void gigaset_isdn_hupD(struct bc_state *bcs) +{ + gig_dbg(DEBUG_CMD, "sending DHUP"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); +} + +/** + * gigaset_isdn_connB() - signal B channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the B channel connection has + * been established. + */ +void gigaset_isdn_connB(struct bc_state *bcs) +{ + gig_dbg(DEBUG_CMD, "sending BCONN"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); +} + +/** + * gigaset_isdn_hupB() - signal B channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the B channel connection has + * been shut down. + */ +void gigaset_isdn_hupB(struct bc_state *bcs) +{ + gig_dbg(DEBUG_CMD, "sending BHUP"); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); +} + +/** + * gigaset_isdn_start() - signal device availability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is available for + * use. + */ +void gigaset_isdn_start(struct cardstate *cs) +{ + gig_dbg(DEBUG_CMD, "sending RUN"); + gigaset_i4l_cmd(cs, ISDN_STAT_RUN); +} + +/** + * gigaset_isdn_stop() - signal device unavailability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is no longer + * available for use. + */ +void gigaset_isdn_stop(struct cardstate *cs) +{ + gig_dbg(DEBUG_CMD, "sending STOP"); + gigaset_i4l_cmd(cs, ISDN_STAT_STOP); +} + +/** + * gigaset_isdn_register() - register 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) +{ + isdn_if *iif; + + pr_info("ISDN4Linux interface\n"); + + iif = kmalloc(sizeof *iif, GFP_KERNEL); + if (!iif) { + pr_err("out of memory\n"); + return 0; + } if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) >= sizeof iif->id) { pr_err("ID too long: %s\n", isdnid); + kfree(iif); return 0; } @@ -593,9 +672,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) if (!register_isdn(iif)) { pr_err("register_isdn failed\n"); + kfree(iif); return 0; } + cs->iif = iif; cs->myid = iif->channels; /* Set my device id */ + cs->hw_hdr_len = HW_HDR_LEN; return 1; } + +/** + * gigaset_isdn_unregister() - unregister from LL + * @cs: device descriptor structure. + * + * Called by main module to unregister the device from the LL. + */ +void gigaset_isdn_unregister(struct cardstate *cs) +{ + gig_dbg(DEBUG_CMD, "sending UNLOAD"); + gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); + kfree(cs->iif); + cs->iif = NULL; +} diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 9f3ef7b4248c..7dabfd35874c 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -500,7 +500,7 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) int result; switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: + case L2_HDLC: result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result); @@ -542,8 +542,9 @@ static inline void hdlc_flush(struct bc_state *bcs) if (likely(bcs->skb != NULL)) skb_trim(bcs->skb, 0); else if (!bcs->ignore) { - if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) - skb_reserve(bcs->skb, HW_HDR_LEN); + bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); + if (bcs->skb) + skb_reserve(bcs->skb, bcs->cs->hw_hdr_len); else dev_err(bcs->cs->dev, "could not allocate skb\n"); } @@ -557,7 +558,9 @@ static inline void hdlc_flush(struct bc_state *bcs) */ static inline void hdlc_done(struct bc_state *bcs) { + struct cardstate *cs = bcs->cs; struct sk_buff *procskb; + unsigned int len; if (unlikely(bcs->ignore)) { bcs->ignore--; @@ -568,32 +571,33 @@ static inline void hdlc_done(struct bc_state *bcs) if ((procskb = bcs->skb) == NULL) { /* previous error */ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); - gigaset_rcv_error(NULL, bcs->cs, bcs); + gigaset_isdn_rcv_err(bcs); } else if (procskb->len < 2) { - dev_notice(bcs->cs->dev, "received short frame (%d octets)\n", + dev_notice(cs->dev, "received short frame (%d octets)\n", procskb->len); bcs->hw.bas->runts++; - gigaset_rcv_error(procskb, bcs->cs, bcs); + dev_kfree_skb(procskb); + gigaset_isdn_rcv_err(bcs); } else if (bcs->fcs != PPP_GOODFCS) { - dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n", - bcs->fcs); + dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); bcs->hw.bas->fcserrs++; - gigaset_rcv_error(procskb, bcs->cs, bcs); + dev_kfree_skb(procskb); + gigaset_isdn_rcv_err(bcs); } else { - procskb->len -= 2; /* subtract FCS */ - procskb->tail -= 2; - gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", - __func__, procskb->len); + len = procskb->len; + __skb_trim(procskb, len -= 2); /* subtract FCS */ + gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len); dump_bytes(DEBUG_STREAM_DUMP, - "rcv data", procskb->data, procskb->len); - bcs->hw.bas->goodbytes += procskb->len; - gigaset_rcv_skb(procskb, bcs->cs, bcs); + "rcv data", procskb->data, len); + bcs->hw.bas->goodbytes += len; + gigaset_skb_rcvd(bcs, procskb); } - if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) - skb_reserve(bcs->skb, HW_HDR_LEN); + bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); + if (bcs->skb) + skb_reserve(bcs->skb, cs->hw_hdr_len); else - dev_err(bcs->cs->dev, "could not allocate skb\n"); + dev_err(cs->dev, "could not allocate skb\n"); bcs->fcs = PPP_INITFCS; } @@ -610,12 +614,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); bcs->hw.bas->alignerrs++; - gigaset_rcv_error(bcs->skb, bcs->cs, bcs); - - if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) - skb_reserve(bcs->skb, HW_HDR_LEN); - else - dev_err(bcs->cs->dev, "could not allocate skb\n"); + gigaset_isdn_rcv_err(bcs); + __skb_trim(bcs->skb, 0); bcs->fcs = PPP_INITFCS; } @@ -648,8 +648,8 @@ static const unsigned char bitcounts[256] = { /* hdlc_unpack * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation) * on a sequence of received data bytes (8 bits each, LSB first) - * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb - * notify of errors via gigaset_rcv_error + * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd + * notify of errors via gigaset_isdn_rcv_err * tally frames, errors etc. in BC structure counters * parameters: * src received data @@ -841,7 +841,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, } /* trans_receive - * pass on received USB frame transparently as SKB via gigaset_rcv_skb + * pass on received USB frame transparently as SKB via gigaset_skb_rcvd * invert bytes * tally frames, errors etc. in BC structure counters * parameters: @@ -852,6 +852,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, static inline void trans_receive(unsigned char *src, unsigned count, struct bc_state *bcs) { + struct cardstate *cs = bcs->cs; struct sk_buff *skb; int dobytes; unsigned char *dst; @@ -862,12 +863,12 @@ static inline void trans_receive(unsigned char *src, unsigned count, return; } if (unlikely((skb = bcs->skb) == NULL)) { - bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); + bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (!skb) { - dev_err(bcs->cs->dev, "could not allocate skb\n"); + dev_err(cs->dev, "could not allocate skb\n"); return; } - skb_reserve(skb, HW_HDR_LEN); + skb_reserve(skb, cs->hw_hdr_len); } bcs->hw.bas->goodbytes += skb->len; dobytes = TRANSBUFSIZE - skb->len; @@ -881,14 +882,14 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (dobytes == 0) { dump_bytes(DEBUG_STREAM_DUMP, "rcv data", skb->data, skb->len); - gigaset_rcv_skb(skb, bcs->cs, bcs); - bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); + gigaset_skb_rcvd(bcs, skb); + bcs->skb = skb = + dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (!skb) { - dev_err(bcs->cs->dev, - "could not allocate skb\n"); + dev_err(cs->dev, "could not allocate skb\n"); return; } - skb_reserve(bcs->skb, HW_HDR_LEN); + skb_reserve(skb, cs->hw_hdr_len); dobytes = TRANSBUFSIZE; } } @@ -897,7 +898,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs) { switch (bcs->proto2) { - case ISDN_PROTO_L2_HDLC: + case L2_HDLC: hdlc_unpack(src, count, bcs); break; default: /* assume transparent */ @@ -981,8 +982,10 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) * @bcs: B channel descriptor structure. * @skb: data to send. * - * Called by i4l.c to queue an skb for sending, and start transmission if + * Called by LL to queue an skb for sending, and start transmission if * necessary. + * Once the payload data has been transmitted completely, gigaset_skb_sent() + * will be called with the first cs->hw_hdr_len bytes of skb->head preserved. * * Return value: * number of bytes accepted for sending (skb->len) if ok, -- cgit v1.2.1 From aaba2b3f8213e1d66e71c351fa7a2b1cbd974d3c Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 6 Oct 2009 12:19:12 +0000 Subject: gigaset: allow building without I4L Add a dummy LL interface to the Gigaset driver so that it can be built and, in a limited way, used without the ISDN4Linux subsystem. Impact: new configuration alternative Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/Kconfig | 13 +++++++- drivers/isdn/gigaset/Makefile | 4 ++- drivers/isdn/gigaset/dummyll.c | 68 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 drivers/isdn/gigaset/dummyll.c (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 18ab8652aa57..6fd2dc1e97fb 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -1,6 +1,5 @@ menuconfig ISDN_DRV_GIGASET tristate "Siemens Gigaset support" - depends on ISDN_I4L select CRC_CCITT select BITREVERSE help @@ -11,9 +10,21 @@ menuconfig ISDN_DRV_GIGASET If you have one of these devices, say M here and for at least one of the connection specific parts that follow. This will build a module called "gigaset". + Note: If you build the ISDN4Linux subsystem (ISDN_I4L) + as a module, you have to build this driver as a module too, + otherwise the Gigaset device won't show up as an ISDN device. if ISDN_DRV_GIGASET +config GIGASET_I4L + bool + depends on ISDN_I4L='y'||(ISDN_I4L='m'&&ISDN_DRV_GIGASET='m') + default y + +config GIGASET_DUMMYLL + bool + default !GIGASET_I4L + config GIGASET_BASE tristate "Gigaset base station support" depends on USB diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index e9d3189f56b7..d429202ba8ef 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile @@ -1,4 +1,6 @@ -gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o +gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o +gigaset-$(CONFIG_GIGASET_I4L) += i4l.o +gigaset-$(CONFIG_GIGASET_DUMMYLL) += dummyll.o usb_gigaset-y := usb-gigaset.o ser_gigaset-y := ser-gigaset.o bas_gigaset-y := bas-gigaset.o isocdata.o diff --git a/drivers/isdn/gigaset/dummyll.c b/drivers/isdn/gigaset/dummyll.c new file mode 100644 index 000000000000..5b27c996af6d --- /dev/null +++ b/drivers/isdn/gigaset/dummyll.c @@ -0,0 +1,68 @@ +/* + * Dummy LL interface for the Gigaset driver + * + * Copyright (c) 2009 by Tilman Schmidt . + * + * ===================================================================== + * 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. + * ===================================================================== + */ + +#include "gigaset.h" + +void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) +{ +} +EXPORT_SYMBOL_GPL(gigaset_skb_sent); + +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) +{ +} +EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); + +void gigaset_isdn_rcv_err(struct bc_state *bcs) +{ +} +EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); + +int gigaset_isdn_icall(struct at_state_t *at_state) +{ + return ICALL_IGNORE; +} + +void gigaset_isdn_connD(struct bc_state *bcs) +{ +} + +void gigaset_isdn_hupD(struct bc_state *bcs) +{ +} + +void gigaset_isdn_connB(struct bc_state *bcs) +{ +} + +void gigaset_isdn_hupB(struct bc_state *bcs) +{ +} + +void gigaset_isdn_start(struct cardstate *cs) +{ +} + +void gigaset_isdn_stop(struct cardstate *cs) +{ +} + +int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) +{ + pr_info("no ISDN subsystem interface\n"); + return 1; +} + +void gigaset_isdn_unregister(struct cardstate *cs) +{ +} -- cgit v1.2.1 From 7bb5fdc2fb021e32703ed1ff0269876bde1fa962 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Tue, 6 Oct 2009 12:19:17 +0000 Subject: gigaset: add Kernel CAPI interface (v3) Add a Kernel CAPI interface to the Gigaset driver. Impact: optional new functionality Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/Kconfig | 18 +- drivers/isdn/gigaset/Makefile | 1 + drivers/isdn/gigaset/capi.c | 2273 +++++++++++++++++++++++++++++++++++++++ drivers/isdn/gigaset/common.c | 26 + drivers/isdn/gigaset/ev-layer.c | 26 +- drivers/isdn/gigaset/gigaset.h | 7 +- 6 files changed, 2335 insertions(+), 16 deletions(-) create mode 100644 drivers/isdn/gigaset/capi.c (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 6fd2dc1e97fb..dcefedc7044a 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -10,20 +10,32 @@ menuconfig ISDN_DRV_GIGASET If you have one of these devices, say M here and for at least one of the connection specific parts that follow. This will build a module called "gigaset". - Note: If you build the ISDN4Linux subsystem (ISDN_I4L) + Note: If you build your ISDN subsystem (ISDN_CAPI or ISDN_I4L) as a module, you have to build this driver as a module too, otherwise the Gigaset device won't show up as an ISDN device. if ISDN_DRV_GIGASET +config GIGASET_CAPI + bool "Gigaset CAPI support (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m') + default ISDN_I4L='n' + help + Build the Gigaset driver as a CAPI 2.0 driver interfacing with + the Kernel CAPI subsystem. To use it with the old ISDN4Linux + subsystem you'll have to enable the capidrv glue driver. + (select ISDN_CAPI_CAPIDRV.) + Say N to build the old native ISDN4Linux variant. + config GIGASET_I4L bool depends on ISDN_I4L='y'||(ISDN_I4L='m'&&ISDN_DRV_GIGASET='m') - default y + default !GIGASET_CAPI config GIGASET_DUMMYLL bool - default !GIGASET_I4L + default !GIGASET_CAPI&&!GIGASET_I4L config GIGASET_BASE tristate "Gigaset base station support" diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index d429202ba8ef..c453b72272a0 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile @@ -1,4 +1,5 @@ gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o +gigaset-$(CONFIG_GIGASET_CAPI) += capi.o gigaset-$(CONFIG_GIGASET_I4L) += i4l.o gigaset-$(CONFIG_GIGASET_DUMMYLL) += dummyll.o usb_gigaset-y := usb-gigaset.o diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c new file mode 100644 index 000000000000..c276a925b36f --- /dev/null +++ b/drivers/isdn/gigaset/capi.c @@ -0,0 +1,2273 @@ +/* + * Kernel CAPI interface for the Gigaset driver + * + * Copyright (c) 2009 by Tilman Schmidt . + * + * ===================================================================== + * 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. + * ===================================================================== + */ + +#include "gigaset.h" +#include +#include +#include +#include + +/* missing from kernelcapi.h */ +#define CapiNcpiNotSupportedByProtocol 0x0001 +#define CapiFlagsNotSupportedByProtocol 0x0002 +#define CapiAlertAlreadySent 0x0003 +#define CapiFacilitySpecificFunctionNotSupported 0x3011 + +/* missing from capicmd.h */ +#define CAPI_CONNECT_IND_BASELEN (CAPI_MSG_BASELEN+4+2+8*1) +#define CAPI_CONNECT_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+3*1) +#define CAPI_CONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+1) +#define CAPI_CONNECT_B3_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+1) +#define CAPI_DATA_B3_REQ_LEN64 (CAPI_MSG_BASELEN+4+4+2+2+2+8) +#define CAPI_DATA_B3_CONF_LEN (CAPI_MSG_BASELEN+4+2+2) +#define CAPI_DISCONNECT_IND_LEN (CAPI_MSG_BASELEN+4+2) +#define CAPI_DISCONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+2+1) +#define CAPI_FACILITY_CONF_BASELEN (CAPI_MSG_BASELEN+4+2+2+1) +/* most _CONF messages contain only Controller/PLCI/NCCI and Info parameters */ +#define CAPI_STDCONF_LEN (CAPI_MSG_BASELEN+4+2) + +#define CAPI_FACILITY_HANDSET 0x0000 +#define CAPI_FACILITY_DTMF 0x0001 +#define CAPI_FACILITY_V42BIS 0x0002 +#define CAPI_FACILITY_SUPPSVC 0x0003 +#define CAPI_FACILITY_WAKEUP 0x0004 +#define CAPI_FACILITY_LI 0x0005 + +#define CAPI_SUPPSVC_GETSUPPORTED 0x0000 + +/* missing from capiutil.h */ +#define CAPIMSG_PLCI_PART(m) CAPIMSG_U8(m, 9) +#define CAPIMSG_NCCI_PART(m) CAPIMSG_U16(m, 10) +#define CAPIMSG_HANDLE_REQ(m) CAPIMSG_U16(m, 18) /* DATA_B3_REQ/_IND only! */ +#define CAPIMSG_FLAGS(m) CAPIMSG_U16(m, 20) +#define CAPIMSG_SETCONTROLLER(m, contr) capimsg_setu8(m, 8, contr) +#define CAPIMSG_SETPLCI_PART(m, plci) capimsg_setu8(m, 9, plci) +#define CAPIMSG_SETNCCI_PART(m, ncci) capimsg_setu16(m, 10, ncci) +#define CAPIMSG_SETFLAGS(m, flags) capimsg_setu16(m, 20, flags) + +/* parameters with differing location in DATA_B3_CONF/_RESP: */ +#define CAPIMSG_SETHANDLE_CONF(m, handle) capimsg_setu16(m, 12, handle) +#define CAPIMSG_SETINFO_CONF(m, info) capimsg_setu16(m, 14, info) + +/* Flags (DATA_B3_REQ/_IND) */ +#define CAPI_FLAGS_DELIVERY_CONFIRMATION 0x04 +#define CAPI_FLAGS_RESERVED (~0x1f) + +/* buffer sizes */ +#define MAX_BC_OCTETS 11 +#define MAX_HLC_OCTETS 3 +#define MAX_NUMBER_DIGITS 20 +#define MAX_FMT_IE_LEN 20 + +/* values for gigaset_capi_appl.connected */ +#define APCONN_NONE 0 /* inactive/listening */ +#define APCONN_SETUP 1 /* connecting */ +#define APCONN_ACTIVE 2 /* B channel up */ + +/* registered application data structure */ +struct gigaset_capi_appl { + struct list_head ctrlist; + struct gigaset_capi_appl *bcnext; + u16 id; + u16 nextMessageNumber; + u32 listenInfoMask; + u32 listenCIPmask; + int connected; +}; + +/* CAPI specific controller data structure */ +struct gigaset_capi_ctr { + struct capi_ctr ctr; + struct list_head appls; + struct sk_buff_head sendqueue; + atomic_t sendqlen; + /* two _cmsg structures possibly used concurrently: */ + _cmsg hcmsg; /* for message composition triggered from hardware */ + _cmsg acmsg; /* for dissection of messages sent from application */ + u8 bc_buf[MAX_BC_OCTETS+1]; + u8 hlc_buf[MAX_HLC_OCTETS+1]; + u8 cgpty_buf[MAX_NUMBER_DIGITS+3]; + u8 cdpty_buf[MAX_NUMBER_DIGITS+2]; +}; + +/* CIP Value table (from CAPI 2.0 standard, ch. 6.1) */ +static struct { + u8 *bc; + u8 *hlc; +} cip2bchlc[] = { + [1] = { "8090A3", NULL }, + /* Speech (A-law) */ + [2] = { "8890", NULL }, + /* Unrestricted digital information */ + [3] = { "8990", NULL }, + /* Restricted digital information */ + [4] = { "9090A3", NULL }, + /* 3,1 kHz audio (A-law) */ + [5] = { "9190", NULL }, + /* 7 kHz audio */ + [6] = { "9890", NULL }, + /* Video */ + [7] = { "88C0C6E6", NULL }, + /* Packet mode */ + [8] = { "8890218F", NULL }, + /* 56 kbit/s rate adaptation */ + [9] = { "9190A5", NULL }, + /* Unrestricted digital information with tones/announcements */ + [16] = { "8090A3", "9181" }, + /* Telephony */ + [17] = { "9090A3", "9184" }, + /* Group 2/3 facsimile */ + [18] = { "8890", "91A1" }, + /* Group 4 facsimile Class 1 */ + [19] = { "8890", "91A4" }, + /* Teletex service basic and mixed mode + and Group 4 facsimile service Classes II and III */ + [20] = { "8890", "91A8" }, + /* Teletex service basic and processable mode */ + [21] = { "8890", "91B1" }, + /* Teletex service basic mode */ + [22] = { "8890", "91B2" }, + /* International interworking for Videotex */ + [23] = { "8890", "91B5" }, + /* Telex */ + [24] = { "8890", "91B8" }, + /* Message Handling Systems in accordance with X.400 */ + [25] = { "8890", "91C1" }, + /* OSI application in accordance with X.200 */ + [26] = { "9190A5", "9181" }, + /* 7 kHz telephony */ + [27] = { "9190A5", "916001" }, + /* Video telephony, first connection */ + [28] = { "8890", "916002" }, + /* Video telephony, second connection */ +}; + +/* + * helper functions + * ================ + */ + +/* + * emit unsupported parameter warning + */ +static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, + char *msgname, char *paramname) +{ + if (param && *param) + dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", + msgname, paramname); +} + +static inline void ignore_cmstruct_param(struct cardstate *cs, _cmstruct param, + char *msgname, char *paramname) +{ + if (param != CAPI_DEFAULT) + dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", + msgname, paramname); +} + +/* + * 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 + */ +static int encode_ie(char *in, u8 *out, int maxlen) +{ + int l = 0; + while (*in) { + if (!ishexdigit(in[0]) || !ishexdigit(in[1]) || l >= maxlen) + return -1; + out[++l] = (hex2bin(in[0]) << 4) + hex2bin(in[1]); + in += 2; + } + out[0] = l; + return l; +} + +/* + * convert an IE from ETSI binary representation including length byte + * to Gigaset hex string + */ +static void decode_ie(u8 *in, char *out) +{ + int i = *in; + while (i-- > 0) { + /* ToDo: conversion to upper case necessary? */ + *out++ = toupper(hex_asc_hi(*++in)); + *out++ = toupper(hex_asc_lo(*in)); + } +} + +/* + * retrieve application data structure for an application ID + */ +static inline struct gigaset_capi_appl * +get_appl(struct gigaset_capi_ctr *iif, u16 appl) +{ + struct gigaset_capi_appl *ap; + + list_for_each_entry(ap, &iif->appls, ctrlist) + if (ap->id == appl) + return ap; + return NULL; +} + +/* + * dump CAPI message to kernel messages for debugging + */ +static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p) +{ +#ifdef CONFIG_GIGASET_DEBUG + _cdebbuf *cdb; + + if (!(gigaset_debuglevel & level)) + return; + + cdb = capi_cmsg2str(p); + if (cdb) { + gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, cdb->buf); + cdebbuf_free(cdb); + } else { + gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, + capi_cmd2str(p->Command, p->Subcommand)); + } +#endif +} + +static inline void dump_rawmsg(enum debuglevel level, const char *tag, + unsigned char *data) +{ +#ifdef CONFIG_GIGASET_DEBUG + char *dbgline; + int i, l; + + if (!(gigaset_debuglevel & level)) + return; + + l = CAPIMSG_LEN(data); + if (l < 12) { + gig_dbg(level, "%s: ??? LEN=%04d", tag, l); + return; + } + gig_dbg(level, "%s: 0x%02x:0x%02x: ID=%03d #0x%04x LEN=%04d NCCI=0x%x", + tag, CAPIMSG_COMMAND(data), CAPIMSG_SUBCOMMAND(data), + CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, + CAPIMSG_CONTROL(data)); + l -= 12; + dbgline = kmalloc(3*l, GFP_ATOMIC); + if (!dbgline) + return; + for (i = 0; i < l; i++) { + dbgline[3*i] = hex_asc_hi(data[12+i]); + dbgline[3*i+1] = hex_asc_lo(data[12+i]); + dbgline[3*i+2] = ' '; + } + dbgline[3*l-1] = '\0'; + gig_dbg(level, " %s", dbgline); + kfree(dbgline); + if (CAPIMSG_COMMAND(data) == CAPI_DATA_B3 && + (CAPIMSG_SUBCOMMAND(data) == CAPI_REQ || + CAPIMSG_SUBCOMMAND(data) == CAPI_IND) && + CAPIMSG_DATALEN(data) > 0) { + l = CAPIMSG_DATALEN(data); + dbgline = kmalloc(3*l, GFP_ATOMIC); + if (!dbgline) + return; + data += CAPIMSG_LEN(data); + for (i = 0; i < l; i++) { + dbgline[3*i] = hex_asc_hi(data[i]); + dbgline[3*i+1] = hex_asc_lo(data[i]); + dbgline[3*i+2] = ' '; + } + dbgline[3*l-1] = '\0'; + gig_dbg(level, " %s", dbgline); + kfree(dbgline); + } +#endif +} + +/* + * format CAPI IE as string + */ + +static const char *format_ie(const char *ie) +{ + static char result[3*MAX_FMT_IE_LEN]; + int len, count; + char *pout = result; + + if (!ie) + return "NULL"; + + count = len = ie[0]; + if (count > MAX_FMT_IE_LEN) + count = MAX_FMT_IE_LEN-1; + while (count--) { + *pout++ = hex_asc_hi(*++ie); + *pout++ = hex_asc_lo(*ie); + *pout++ = ' '; + } + if (len > MAX_FMT_IE_LEN) { + *pout++ = '.'; + *pout++ = '.'; + *pout++ = '.'; + } + *--pout = 0; + return result; +} + + +/* + * driver interface functions + * ========================== + */ + +/** + * gigaset_skb_sent() - acknowledge transmission of outgoing skb + * @bcs: B channel descriptor structure. + * @skb: sent data. + * + * Called by hardware module {bas,ser,usb}_gigaset when the data in a + * skb has been successfully sent, for signalling completion to the LL. + */ +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; + struct sk_buff *cskb; + u16 flags; + + /* update statistics */ + ++bcs->trans_up; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + + /* don't send further B3 messages if disconnected */ + if (ap->connected < APCONN_ACTIVE) { + gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); + return; + } + + /* ToDo: honor unset "delivery confirmation" bit */ + flags = CAPIMSG_FLAGS(dskb->head); + + /* build DATA_B3_CONF message */ + cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); + if (!cskb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + /* frequent message, avoid _cmsg overhead */ + CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN); + 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_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)); + if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) + CAPIMSG_SETINFO_CONF(cskb->data, + CapiFlagsNotSupportedByProtocol); + else + CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR); + + /* emit message */ + dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data); + capi_ctr_handle_message(&iif->ctr, ap->id, cskb); +} +EXPORT_SYMBOL_GPL(gigaset_skb_sent); + +/** + * gigaset_skb_rcvd() - pass received skb to LL + * @bcs: B channel descriptor structure. + * @skb: received data. + * + * Called by hardware module {bas,ser,usb}_gigaset when user data has + * been successfully received, for passing to the LL. + * Warning: skb must not be accessed anymore! + */ +void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap = bcs->ap; + int len = skb->len; + + /* update statistics */ + bcs->trans_down++; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + + /* don't send further B3 messages if disconnected */ + if (ap->connected < APCONN_ACTIVE) { + gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); + dev_kfree_skb(skb); + return; + } + + /* + * prepend DATA_B3_IND message to payload + * Parameters: NCCI = 1, all others 0/unused + * frequent message, avoid _cmsg overhead + */ + skb_push(skb, CAPI_DATA_B3_REQ_LEN); + CAPIMSG_SETLEN(skb->data, CAPI_DATA_B3_REQ_LEN); + CAPIMSG_SETAPPID(skb->data, ap->id); + CAPIMSG_SETCOMMAND(skb->data, CAPI_DATA_B3); + CAPIMSG_SETSUBCOMMAND(skb->data, CAPI_IND); + CAPIMSG_SETMSGID(skb->data, ap->nextMessageNumber++); + CAPIMSG_SETCONTROLLER(skb->data, iif->ctr.cnr); + CAPIMSG_SETPLCI_PART(skb->data, bcs->channel + 1); + CAPIMSG_SETNCCI_PART(skb->data, 1); + /* Data parameter not used */ + CAPIMSG_SETDATALEN(skb->data, len); + /* Data handle parameter not used */ + CAPIMSG_SETFLAGS(skb->data, 0); + /* Data64 parameter not present */ + + /* emit message */ + dump_rawmsg(DEBUG_LLDATA, "DATA_B3_IND", skb->data); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} +EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); + +/** + * gigaset_isdn_rcv_err() - signal receive error + * @bcs: B channel descriptor structure. + * + * Called by hardware module {bas,ser,usb}_gigaset when a receive error + * has occurred, for signalling to the LL. + */ +void gigaset_isdn_rcv_err(struct bc_state *bcs) +{ + /* if currently ignoring packets, just count down */ + if (bcs->ignore) { + bcs->ignore--; + return; + } + + /* update statistics */ + bcs->corrupted++; + + /* ToDo: signal error -> LL */ +} +EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); + +/** + * gigaset_isdn_icall() - signal incoming call + * @at_state: connection state structure. + * + * Called by main module at tasklet level to notify the LL that an incoming + * call has been received. @at_state contains the parameters of the call. + * + * Return value: call disposition (ICALL_*) + */ +int gigaset_isdn_icall(struct at_state_t *at_state) +{ + struct cardstate *cs = at_state->cs; + struct bc_state *bcs = at_state->bcs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap; + u32 actCIPmask; + struct sk_buff *skb; + unsigned int msgsize; + int i; + + /* + * ToDo: signal calls without a free B channel, too + * (requires a u8 handle for the at_state structure that can + * be stored in the PLCI and used in the CONNECT_RESP message + * handler to retrieve it) + */ + if (!bcs) + return ICALL_IGNORE; + + /* prepare CONNECT_IND message, using B channel number as PLCI */ + capi_cmsg_header(&iif->hcmsg, 0, CAPI_CONNECT, CAPI_IND, 0, + iif->ctr.cnr | ((bcs->channel + 1) << 8)); + + /* minimum size, all structs empty */ + msgsize = CAPI_CONNECT_IND_BASELEN; + + /* Bearer Capability (mandatory) */ + if (at_state->str_var[STR_ZBC]) { + /* pass on BC from Gigaset */ + if (encode_ie(at_state->str_var[STR_ZBC], iif->bc_buf, + MAX_BC_OCTETS) < 0) { + dev_warn(cs->dev, "RING ignored - bad BC %s\n", + at_state->str_var[STR_ZBC]); + return ICALL_IGNORE; + } + + /* look up corresponding CIP value */ + iif->hcmsg.CIPValue = 0; /* default if nothing found */ + for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) + if (cip2bchlc[i].bc != NULL && + cip2bchlc[i].hlc == NULL && + !strcmp(cip2bchlc[i].bc, + at_state->str_var[STR_ZBC])) { + iif->hcmsg.CIPValue = i; + break; + } + } else { + /* no BC (internal call): assume CIP 1 (speech, A-law) */ + iif->hcmsg.CIPValue = 1; + encode_ie(cip2bchlc[1].bc, iif->bc_buf, MAX_BC_OCTETS); + } + iif->hcmsg.BC = iif->bc_buf; + msgsize += iif->hcmsg.BC[0]; + + /* High Layer Compatibility (optional) */ + if (at_state->str_var[STR_ZHLC]) { + /* pass on HLC from Gigaset */ + if (encode_ie(at_state->str_var[STR_ZHLC], iif->hlc_buf, + MAX_HLC_OCTETS) < 0) { + dev_warn(cs->dev, "RING ignored - bad HLC %s\n", + at_state->str_var[STR_ZHLC]); + return ICALL_IGNORE; + } + iif->hcmsg.HLC = iif->hlc_buf; + msgsize += iif->hcmsg.HLC[0]; + + /* look up corresponding CIP value */ + /* keep BC based CIP value if none found */ + if (at_state->str_var[STR_ZBC]) + for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) + if (cip2bchlc[i].hlc != NULL && + !strcmp(cip2bchlc[i].hlc, + at_state->str_var[STR_ZHLC]) && + !strcmp(cip2bchlc[i].bc, + at_state->str_var[STR_ZBC])) { + iif->hcmsg.CIPValue = i; + break; + } + } + + /* Called Party Number (optional) */ + if (at_state->str_var[STR_ZCPN]) { + i = strlen(at_state->str_var[STR_ZCPN]); + if (i > MAX_NUMBER_DIGITS) { + dev_warn(cs->dev, "RING ignored - bad number %s\n", + at_state->str_var[STR_ZBC]); + return ICALL_IGNORE; + } + iif->cdpty_buf[0] = i + 1; + iif->cdpty_buf[1] = 0x80; /* type / numbering plan unknown */ + memcpy(iif->cdpty_buf+2, at_state->str_var[STR_ZCPN], i); + iif->hcmsg.CalledPartyNumber = iif->cdpty_buf; + msgsize += iif->hcmsg.CalledPartyNumber[0]; + } + + /* Calling Party Number (optional) */ + if (at_state->str_var[STR_NMBR]) { + i = strlen(at_state->str_var[STR_NMBR]); + if (i > MAX_NUMBER_DIGITS) { + dev_warn(cs->dev, "RING ignored - bad number %s\n", + at_state->str_var[STR_ZBC]); + return ICALL_IGNORE; + } + iif->cgpty_buf[0] = i + 2; + iif->cgpty_buf[1] = 0x00; /* type / numbering plan unknown */ + iif->cgpty_buf[2] = 0x80; /* pres. allowed, not screened */ + memcpy(iif->cgpty_buf+3, at_state->str_var[STR_NMBR], i); + iif->hcmsg.CallingPartyNumber = iif->cgpty_buf; + msgsize += iif->hcmsg.CallingPartyNumber[0]; + } + + /* remaining parameters (not supported, always left NULL): + * - CalledPartySubaddress + * - CallingPartySubaddress + * - AdditionalInfo + * - BChannelinformation + * - Keypadfacility + * - Useruserdata + * - Facilitydataarray + */ + + gig_dbg(DEBUG_CMD, "icall: PLCI %x CIP %d BC %s", + iif->hcmsg.adr.adrPLCI, iif->hcmsg.CIPValue, + format_ie(iif->hcmsg.BC)); + gig_dbg(DEBUG_CMD, "icall: HLC %s", + format_ie(iif->hcmsg.HLC)); + gig_dbg(DEBUG_CMD, "icall: CgPty %s", + format_ie(iif->hcmsg.CallingPartyNumber)); + gig_dbg(DEBUG_CMD, "icall: CdPty %s", + format_ie(iif->hcmsg.CalledPartyNumber)); + + /* scan application list for matching listeners */ + bcs->ap = NULL; + actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); + list_for_each_entry(ap, &iif->appls, ctrlist) + if (actCIPmask & ap->listenCIPmask) { + /* build CONNECT_IND message for this application */ + iif->hcmsg.ApplId = ap->id; + iif->hcmsg.Messagenumber = ap->nextMessageNumber++; + + skb = alloc_skb(msgsize, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", + __func__); + break; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + + /* add to listeners on this B channel, update state */ + ap->bcnext = bcs->ap; + bcs->ap = ap; + bcs->chstate |= CHS_NOTIFY_LL; + ap->connected = APCONN_SETUP; + + /* emit message */ + capi_ctr_handle_message(&iif->ctr, ap->id, skb); + } + + /* + * Return "accept" if any listeners. + * Gigaset will send ALERTING. + * There doesn't seem to be a way to avoid this. + */ + return bcs->ap ? ICALL_ACCEPT : ICALL_IGNORE; +} + +/* + * send a DISCONNECT_IND message to an application + * does not sleep, clobbers the controller's hcmsg structure + */ +static void send_disconnect_ind(struct bc_state *bcs, + struct gigaset_capi_appl *ap, u16 reason) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct sk_buff *skb; + + if (ap->connected == APCONN_NONE) + return; + + capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8)); + iif->hcmsg.Reason = reason; + skb = alloc_skb(CAPI_DISCONNECT_IND_LEN, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + ap->connected = APCONN_NONE; + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/* + * send a DISCONNECT_B3_IND message to an application + * Parameters: NCCI = 1, NCPI empty, Reason_B3 = 0 + * does not sleep, clobbers the controller's hcmsg structure + */ +static void send_disconnect_b3_ind(struct bc_state *bcs, + struct gigaset_capi_appl *ap) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct sk_buff *skb; + + /* nothing to do if no logical connection active */ + if (ap->connected < APCONN_ACTIVE) + return; + ap->connected = APCONN_SETUP; + + capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); + skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, + __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/** + * gigaset_isdn_connD() - signal D channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module at tasklet level to notify the LL that the D channel + * connection has been established. + */ +void gigaset_isdn_connD(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap = bcs->ap; + struct sk_buff *skb; + unsigned int msgsize; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + while (ap->bcnext) { + /* this should never happen */ + dev_warn(cs->dev, "%s: dropping extra application %u\n", + __func__, ap->bcnext->id); + send_disconnect_ind(bcs, ap->bcnext, + CapiCallGivenToOtherApplication); + ap->bcnext = ap->bcnext->bcnext; + } + if (ap->connected == APCONN_NONE) { + dev_warn(cs->dev, "%s: application %u not connected\n", + __func__, ap->id); + return; + } + + /* prepare CONNECT_ACTIVE_IND message + * Note: LLC not supported by device + */ + capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_CONNECT_ACTIVE, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8)); + + /* minimum size, all structs empty */ + msgsize = CAPI_CONNECT_ACTIVE_IND_BASELEN; + + /* ToDo: set parameter: Connected number + * (requires ev-layer state machine extension to collect + * ZCON device reply) + */ + + /* build and emit CONNECT_ACTIVE_IND message */ + skb = alloc_skb(msgsize, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/** + * gigaset_isdn_hupD() - signal D channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module at tasklet level to notify the LL that the D channel + * connection has been shut down. + */ +void gigaset_isdn_hupD(struct bc_state *bcs) +{ + struct gigaset_capi_appl *ap; + + /* + * ToDo: pass on reason code reported by device + * (requires ev-layer state machine extension to collect + * ZCAU device reply) + */ + for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { + send_disconnect_b3_ind(bcs, ap); + send_disconnect_ind(bcs, ap, 0); + } + bcs->ap = NULL; +} + +/** + * gigaset_isdn_connB() - signal B channel connect + * @bcs: B channel descriptor structure. + * + * Called by main module at tasklet level to notify the LL that the B channel + * connection has been established. + */ +void gigaset_isdn_connB(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_ctr *iif = cs->iif; + struct gigaset_capi_appl *ap = bcs->ap; + struct sk_buff *skb; + unsigned int msgsize; + u8 command; + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + while (ap->bcnext) { + /* this should never happen */ + dev_warn(cs->dev, "%s: dropping extra application %u\n", + __func__, ap->bcnext->id); + send_disconnect_ind(bcs, ap->bcnext, + CapiCallGivenToOtherApplication); + ap->bcnext = ap->bcnext->bcnext; + } + if (!ap->connected) { + dev_warn(cs->dev, "%s: application %u not connected\n", + __func__, ap->id); + return; + } + + /* + * emit CONNECT_B3_ACTIVE_IND if we already got CONNECT_B3_REQ; + * otherwise we have to emit CONNECT_B3_IND first, and follow up with + * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP + * Parameters in both cases always: NCCI = 1, NCPI empty + */ + if (ap->connected >= APCONN_ACTIVE) { + command = CAPI_CONNECT_B3_ACTIVE; + msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; + } else { + command = CAPI_CONNECT_B3; + msgsize = CAPI_CONNECT_B3_IND_BASELEN; + } + capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND, + ap->nextMessageNumber++, + iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); + skb = alloc_skb(msgsize, GFP_ATOMIC); + if (!skb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); + ap->connected = APCONN_ACTIVE; + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/** + * gigaset_isdn_hupB() - signal B channel hangup + * @bcs: B channel descriptor structure. + * + * Called by main module to notify the LL that the B channel connection has + * been shut down. + */ +void gigaset_isdn_hupB(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + struct gigaset_capi_appl *ap = bcs->ap; + + /* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */ + + if (!ap) { + dev_err(cs->dev, "%s: no application\n", __func__); + return; + } + + send_disconnect_b3_ind(bcs, ap); +} + +/** + * gigaset_isdn_start() - signal device availability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is available for + * use. + */ +void gigaset_isdn_start(struct cardstate *cs) +{ + struct gigaset_capi_ctr *iif = cs->iif; + + /* fill profile data: manufacturer name */ + strcpy(iif->ctr.manu, "Siemens"); + /* CAPI and device version */ + iif->ctr.version.majorversion = 2; /* CAPI 2.0 */ + iif->ctr.version.minorversion = 0; + /* ToDo: check/assert cs->gotfwver? */ + iif->ctr.version.majormanuversion = cs->fwver[0]; + iif->ctr.version.minormanuversion = cs->fwver[1]; + /* number of B channels supported */ + iif->ctr.profile.nbchannel = cs->channels; + /* global options: internal controller, supplementary services */ + iif->ctr.profile.goptions = 0x11; + /* B1 protocols: 64 kbit/s HDLC or transparent */ + iif->ctr.profile.support1 = 0x03; + /* B2 protocols: transparent only */ + /* ToDo: X.75 SLP ? */ + iif->ctr.profile.support2 = 0x02; + /* B3 protocols: transparent only */ + iif->ctr.profile.support3 = 0x01; + /* no serial number */ + strcpy(iif->ctr.serial, "0"); + capi_ctr_ready(&iif->ctr); +} + +/** + * gigaset_isdn_stop() - signal device unavailability + * @cs: device descriptor structure. + * + * Called by main module to notify the LL that the device is no longer + * available for use. + */ +void gigaset_isdn_stop(struct cardstate *cs) +{ + struct gigaset_capi_ctr *iif = cs->iif; + capi_ctr_down(&iif->ctr); +} + +/* + * kernel CAPI callback methods + * ============================ + */ + +/* + * load firmware + */ +static int gigaset_load_firmware(struct capi_ctr *ctr, capiloaddata *data) +{ + struct cardstate *cs = ctr->driverdata; + + /* AVM specific operation, not needed for Gigaset -- ignore */ + dev_notice(cs->dev, "load_firmware ignored\n"); + + return 0; +} + +/* + * reset (deactivate) controller + */ +static void gigaset_reset_ctr(struct capi_ctr *ctr) +{ + struct cardstate *cs = ctr->driverdata; + + /* AVM specific operation, not needed for Gigaset -- ignore */ + dev_notice(cs->dev, "reset_ctr ignored\n"); +} + +/* + * register CAPI application + */ +static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, + capi_register_params *rp) +{ + struct gigaset_capi_ctr *iif + = container_of(ctr, struct gigaset_capi_ctr, ctr); + struct cardstate *cs = ctr->driverdata; + struct gigaset_capi_appl *ap; + + list_for_each_entry(ap, &iif->appls, ctrlist) + if (ap->id == appl) { + dev_notice(cs->dev, + "application %u already registered\n", appl); + return; + } + + ap = kzalloc(sizeof(*ap), GFP_KERNEL); + if (!ap) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + ap->id = appl; + + list_add(&ap->ctrlist, &iif->appls); +} + +/* + * release CAPI application + */ +static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl) +{ + struct gigaset_capi_ctr *iif + = container_of(ctr, struct gigaset_capi_ctr, ctr); + struct cardstate *cs = iif->ctr.driverdata; + struct gigaset_capi_appl *ap, *tmp; + + list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist) + if (ap->id == appl) { + if (ap->connected != APCONN_NONE) { + dev_err(cs->dev, + "%s: application %u still connected\n", + __func__, ap->id); + /* ToDo: clear active connection */ + } + list_del(&ap->ctrlist); + kfree(ap); + } + +} + +/* + * ===================================================================== + * outgoing CAPI message handler + * ===================================================================== + */ + +/* + * helper function: emit reply message with given Info value + */ +static void send_conf(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb, + u16 info) +{ + /* + * _CONF replies always only have NCCI and Info parameters + * so they'll fit into the _REQ message skb + */ + capi_cmsg_answer(&iif->acmsg); + iif->acmsg.Info = info; + capi_cmsg2message(&iif->acmsg, skb->data); + __skb_trim(skb, CAPI_STDCONF_LEN); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/* + * process FACILITY_REQ message + */ +static void do_facility_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + struct sk_buff *cskb; + u8 *pparam; + unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; + u16 function, info; + static u8 confparam[10]; /* max. 9 octets + length byte */ + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* + * Facility Request Parameter is not decoded by capi_message2cmsg() + * encoding depends on Facility Selector + */ + switch (iif->acmsg.FacilitySelector) { + case CAPI_FACILITY_DTMF: /* ToDo */ + info = CapiFacilityNotSupported; + confparam[0] = 2; /* length */ + /* DTMF information: Unknown DTMF request */ + capimsg_setu16(confparam, 1, 2); + break; + + case CAPI_FACILITY_V42BIS: /* not supported */ + info = CapiFacilityNotSupported; + confparam[0] = 2; /* length */ + /* V.42 bis information: not available */ + capimsg_setu16(confparam, 1, 1); + break; + + case CAPI_FACILITY_SUPPSVC: + /* decode Function parameter */ + pparam = iif->acmsg.FacilityRequestParameter; + if (pparam == NULL || *pparam < 2) { + dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", + "Facility Request Parameter"); + send_conf(iif, ap, skb, CapiIllMessageParmCoding); + return; + } + function = CAPIMSG_U16(pparam, 1); + switch (function) { + case CAPI_SUPPSVC_GETSUPPORTED: + info = CapiSuccess; + /* Supplementary Service specific parameter */ + confparam[3] = 6; /* length */ + /* Supplementary services info: Success */ + capimsg_setu16(confparam, 4, CapiSuccess); + /* Supported Services: none */ + capimsg_setu32(confparam, 6, 0); + break; + /* ToDo: add supported services */ + default: + info = CapiFacilitySpecificFunctionNotSupported; + /* Supplementary Service specific parameter */ + confparam[3] = 2; /* length */ + /* Supplementary services info: not supported */ + capimsg_setu16(confparam, 4, + CapiSupplementaryServiceNotSupported); + } + + /* Facility confirmation parameter */ + confparam[0] = confparam[3] + 3; /* total length */ + /* Function: copy from _REQ message */ + capimsg_setu16(confparam, 1, function); + /* Supplementary Service specific parameter already set above */ + break; + + case CAPI_FACILITY_WAKEUP: /* ToDo */ + info = CapiFacilityNotSupported; + confparam[0] = 2; /* length */ + /* Number of accepted awake request parameters: 0 */ + capimsg_setu16(confparam, 1, 0); + break; + + default: + info = CapiFacilityNotSupported; + confparam[0] = 0; /* empty struct */ + } + + /* send FACILITY_CONF with given Info and confirmation parameter */ + capi_cmsg_answer(&iif->acmsg); + iif->acmsg.Info = info; + iif->acmsg.FacilityConfirmationParameter = confparam; + msgsize += confparam[0]; /* length */ + cskb = alloc_skb(msgsize, GFP_ATOMIC); + if (!cskb) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + return; + } + capi_cmsg2message(&iif->acmsg, __skb_put(cskb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, cskb); +} + + +/* + * process LISTEN_REQ message + * just store the masks in the application data structure + */ +static void do_listen_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* store listening parameters */ + ap->listenInfoMask = iif->acmsg.InfoMask; + ap->listenCIPmask = iif->acmsg.CIPmask; + send_conf(iif, ap, skb, CapiSuccess); +} + +/* + * process ALERT_REQ message + * nothing to do, Gigaset always alerts anyway + */ +static void do_alert_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + send_conf(iif, ap, skb, CapiAlertAlreadySent); +} + +/* + * process CONNECT_REQ message + * allocate a B channel, prepare dial commands, queue a DIAL event, + * emit CONNECT_CONF reply + */ +static void do_connect_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; + char **commands; + char *s; + u8 *pp; + int i, l; + u16 info; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* get free B channel & construct PLCI */ + bcs = gigaset_get_free_channel(cs); + if (!bcs) { + dev_notice(cs->dev, "%s: no B channel available\n", + "CONNECT_REQ"); + send_conf(iif, ap, skb, CapiNoPlciAvailable); + return; + } + ap->bcnext = NULL; + bcs->ap = ap; + cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; + + /* build command table */ + commands = kzalloc(AT_NUM*(sizeof *commands), GFP_KERNEL); + if (!commands) + goto oom; + + /* encode parameter: Called party number */ + pp = cmsg->CalledPartyNumber; + if (pp == NULL || *pp == 0) { + dev_notice(cs->dev, "%s: %s missing\n", + "CONNECT_REQ", "Called party number"); + info = CapiIllMessageParmCoding; + goto error; + } + l = *pp++; + /* check type of number/numbering plan byte */ + switch (*pp) { + case 0x80: /* unknown type / unknown numbering plan */ + case 0x81: /* unknown type / ISDN/Telephony numbering plan */ + break; + default: /* others: warn about potential misinterpretation */ + dev_notice(cs->dev, "%s: %s type/plan 0x%02x unsupported\n", + "CONNECT_REQ", "Called party number", *pp); + } + pp++; + l--; + /* translate "**" internal call prefix to CTP value */ + if (l >= 2 && pp[0] == '*' && pp[1] == '*') { + s = "^SCTP=0\r"; + pp += 2; + l -= 2; + } else { + s = "^SCTP=1\r"; + } + commands[AT_TYPE] = kstrdup(s, GFP_KERNEL); + if (!commands[AT_TYPE]) + goto oom; + commands[AT_DIAL] = kmalloc(l+3, GFP_KERNEL); + if (!commands[AT_DIAL]) + goto oom; + snprintf(commands[AT_DIAL], l+3, "D%*s\r", l, pp); + + /* encode parameter: Calling party number */ + pp = cmsg->CallingPartyNumber; + if (pp != NULL && *pp > 0) { + l = *pp++; + + /* check type of number/numbering plan byte */ + /* ToDo: allow for/handle Ext=1? */ + switch (*pp) { + case 0x00: /* unknown type / unknown numbering plan */ + case 0x01: /* unknown type / ISDN/Telephony num. plan */ + break; + default: + dev_notice(cs->dev, + "%s: %s type/plan 0x%02x unsupported\n", + "CONNECT_REQ", "Calling party number", *pp); + } + pp++; + l--; + + /* check presentation indicator */ + if (!l) { + dev_notice(cs->dev, "%s: %s IE truncated\n", + "CONNECT_REQ", "Calling party number"); + info = CapiIllMessageParmCoding; + goto error; + } + switch (*pp & 0xfc) { /* ignore Screening indicator */ + case 0x80: /* Presentation allowed */ + s = "^SCLIP=1\r"; + break; + case 0xa0: /* Presentation restricted */ + s = "^SCLIP=0\r"; + break; + default: + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_REQ", + "Presentation/Screening indicator", + *pp); + s = "^SCLIP=1\r"; + } + commands[AT_CLIP] = kstrdup(s, GFP_KERNEL); + if (!commands[AT_CLIP]) + goto oom; + pp++; + l--; + + if (l) { + /* number */ + commands[AT_MSN] = kmalloc(l+8, GFP_KERNEL); + if (!commands[AT_MSN]) + goto oom; + snprintf(commands[AT_MSN], l+8, "^SMSN=%*s\r", l, pp); + } + } + + /* check parameter: CIP Value */ + 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); + info = CapiCipValueUnknown; + goto error; + } + + /* check/encode parameter: BC */ + if (cmsg->BC && cmsg->BC[0]) { + /* explicit BC overrides CIP */ + l = 2*cmsg->BC[0] + 7; + commands[AT_BC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_BC]) + goto oom; + strcpy(commands[AT_BC], "^SBC="); + decode_ie(cmsg->BC, commands[AT_BC]+5); + strcpy(commands[AT_BC] + l - 2, "\r"); + } else if (cip2bchlc[cmsg->CIPValue].bc) { + l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7; + commands[AT_BC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_BC]) + goto oom; + snprintf(commands[AT_BC], l, "^SBC=%s\r", + cip2bchlc[cmsg->CIPValue].bc); + } + + /* check/encode parameter: HLC */ + if (cmsg->HLC && cmsg->HLC[0]) { + /* explicit HLC overrides CIP */ + l = 2*cmsg->HLC[0] + 7; + commands[AT_HLC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_HLC]) + goto oom; + strcpy(commands[AT_HLC], "^SHLC="); + decode_ie(cmsg->HLC, commands[AT_HLC]+5); + strcpy(commands[AT_HLC] + l - 2, "\r"); + } else if (cip2bchlc[cmsg->CIPValue].hlc) { + l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7; + commands[AT_HLC] = kmalloc(l, GFP_KERNEL); + if (!commands[AT_HLC]) + goto oom; + snprintf(commands[AT_HLC], l, "^SHLC=%s\r", + cip2bchlc[cmsg->CIPValue].hlc); + } + + /* check/encode parameter: B Protocol */ + if (cmsg->BProtocol == CAPI_DEFAULT) { + bcs->proto2 = L2_HDLC; + dev_warn(cs->dev, + "B2 Protocol X.75 SLP unsupported, using Transparent\n"); + } else { + switch (cmsg->B1protocol) { + case 0: + bcs->proto2 = L2_HDLC; + break; + case 1: + bcs->proto2 = L2_BITSYNC; + break; + default: + dev_warn(cs->dev, + "B1 Protocol %u unsupported, using Transparent\n", + cmsg->B1protocol); + bcs->proto2 = L2_BITSYNC; + } + if (cmsg->B2protocol != 1) + dev_warn(cs->dev, + "B2 Protocol %u unsupported, using Transparent\n", + cmsg->B2protocol); + if (cmsg->B3protocol != 0) + dev_warn(cs->dev, + "B3 Protocol %u unsupported, using Transparent\n", + cmsg->B3protocol); + ignore_cstruct_param(cs, cmsg->B1configuration, + "CONNECT_REQ", "B1 Configuration"); + ignore_cstruct_param(cs, cmsg->B2configuration, + "CONNECT_REQ", "B2 Configuration"); + ignore_cstruct_param(cs, cmsg->B3configuration, + "CONNECT_REQ", "B3 Configuration"); + } + commands[AT_PROTO] = kmalloc(9, GFP_KERNEL); + if (!commands[AT_PROTO]) + goto oom; + snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); + + /* ToDo: check/encode remaining parameters */ + ignore_cstruct_param(cs, cmsg->CalledPartySubaddress, + "CONNECT_REQ", "Called pty subaddr"); + ignore_cstruct_param(cs, cmsg->CallingPartySubaddress, + "CONNECT_REQ", "Calling pty subaddr"); + ignore_cstruct_param(cs, cmsg->LLC, + "CONNECT_REQ", "LLC"); + ignore_cmstruct_param(cs, cmsg->AdditionalInfo, + "CONNECT_REQ", "Additional Info"); + + /* encode parameter: B channel to use */ + commands[AT_ISO] = kmalloc(9, GFP_KERNEL); + if (!commands[AT_ISO]) + goto oom; + snprintf(commands[AT_ISO], 9, "^SISO=%u\r", + (unsigned) bcs->channel + 1); + + /* 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"); + gigaset_schedule_event(cs); + ap->connected = APCONN_SETUP; + send_conf(iif, ap, skb, CapiSuccess); + return; + +oom: + dev_err(cs->dev, "%s: out of memory\n", __func__); + info = CAPI_MSGOSRESOURCEERR; +error: + if (commands) + for (i = 0; i < AT_NUM; i++) + kfree(commands[i]); + kfree(commands); + gigaset_free_channel(bcs); + send_conf(iif, ap, skb, info); +} + +/* + * process CONNECT_RESP message + * checks protocol parameters and queues an ACCEPT or HUP event + */ +static void do_connect_resp(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; + struct gigaset_capi_appl *oap; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + dev_kfree_skb(skb); + + /* extract and check channel number from PLCI */ + channel = (cmsg->adr.adrPLCI >> 8) & 0xff; + if (!channel || channel > cs->channels) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_RESP", "PLCI", cmsg->adr.adrPLCI); + return; + } + bcs = cs->bcs + channel - 1; + + switch (cmsg->Reject) { + case 0: /* Accept */ + /* drop all competing applications, keep only this one */ + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) + if (oap != ap) + send_disconnect_ind(bcs, oap, + CapiCallGivenToOtherApplication); + ap->bcnext = NULL; + bcs->ap = ap; + bcs->chstate |= CHS_NOTIFY_LL; + + /* check/encode B channel protocol */ + if (cmsg->BProtocol == CAPI_DEFAULT) { + bcs->proto2 = L2_HDLC; + dev_warn(cs->dev, + "B2 Protocol X.75 SLP unsupported, using Transparent\n"); + } else { + switch (cmsg->B1protocol) { + case 0: + bcs->proto2 = L2_HDLC; + break; + case 1: + bcs->proto2 = L2_BITSYNC; + break; + default: + dev_warn(cs->dev, + "B1 Protocol %u unsupported, using Transparent\n", + cmsg->B1protocol); + bcs->proto2 = L2_BITSYNC; + } + if (cmsg->B2protocol != 1) + dev_warn(cs->dev, + "B2 Protocol %u unsupported, using Transparent\n", + cmsg->B2protocol); + if (cmsg->B3protocol != 0) + dev_warn(cs->dev, + "B3 Protocol %u unsupported, using Transparent\n", + cmsg->B3protocol); + ignore_cstruct_param(cs, cmsg->B1configuration, + "CONNECT_RESP", "B1 Configuration"); + ignore_cstruct_param(cs, cmsg->B2configuration, + "CONNECT_RESP", "B2 Configuration"); + ignore_cstruct_param(cs, cmsg->B3configuration, + "CONNECT_RESP", "B3 Configuration"); + } + + /* ToDo: check/encode remaining parameters */ + ignore_cstruct_param(cs, cmsg->ConnectedNumber, + "CONNECT_RESP", "Connected Number"); + ignore_cstruct_param(cs, cmsg->ConnectedSubaddress, + "CONNECT_RESP", "Connected Subaddress"); + ignore_cstruct_param(cs, cmsg->LLC, + "CONNECT_RESP", "LLC"); + ignore_cmstruct_param(cs, cmsg->AdditionalInfo, + "CONNECT_RESP", "Additional Info"); + + /* Accept call */ + 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; + + case 1: /* Ignore */ + /* send DISCONNECT_IND to this application */ + send_disconnect_ind(bcs, ap, 0); + + /* remove it from the list of listening apps */ + if (bcs->ap == ap) { + bcs->ap = ap->bcnext; + if (bcs->ap == NULL) + /* last one: stop ev-layer hupD notifications */ + bcs->chstate &= ~CHS_NOTIFY_LL; + return; + } + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) { + if (oap->bcnext == ap) { + oap->bcnext = oap->bcnext->bcnext; + return; + } + } + dev_err(cs->dev, "%s: application %u not found\n", + __func__, ap->id); + return; + + default: /* Reject */ + /* drop all competing applications, keep only this one */ + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) + if (oap != ap) + send_disconnect_ind(bcs, oap, + CapiCallGivenToOtherApplication); + ap->bcnext = NULL; + bcs->ap = ap; + + /* reject call - will trigger DISCONNECT_IND for this app */ + dev_info(cs->dev, "%s: Reject=%x\n", + "CONNECT_RESP", cmsg->Reject); + 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; + } +} + +/* + * process CONNECT_B3_REQ message + * build NCCI and emit CONNECT_B3_CONF reply + */ +static void do_connect_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number from PLCI */ + channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + if (!channel || channel > cs->channels) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_B3_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + + /* mark logical connection active */ + ap->connected = APCONN_ACTIVE; + + /* build NCCI: always 1 (one B3 connection only) */ + iif->acmsg.adr.adrNCCI |= 1 << 16; + + /* NCPI parameter: not applicable for B3 Transparent */ + ignore_cstruct_param(cs, iif->acmsg.NCPI, + "CONNECT_B3_REQ", "NCPI"); + send_conf(iif, ap, skb, + (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); +} + +/* + * process CONNECT_B3_RESP message + * Depending on the Reject parameter, either emit CONNECT_B3_ACTIVE_IND + * or queue EV_HUP and emit DISCONNECT_B3_IND. + * The emitted message is always shorter than the received one, + * allowing to reuse the skb. + */ +static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + struct bc_state *bcs = NULL; + int channel; + unsigned int msgsize; + u8 command; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number and NCCI */ + channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + if (!channel || channel > cs->channels || + ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "CONNECT_B3_RESP", "NCCI", iif->acmsg.adr.adrNCCI); + dev_kfree_skb(skb); + return; + } + bcs = &cs->bcs[channel-1]; + + if (iif->acmsg.Reject) { + /* Reject: clear B3 connect received flag */ + ap->connected = APCONN_SETUP; + + /* 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); + return; + } + gig_dbg(DEBUG_CMD, "scheduling HUP"); + gigaset_schedule_event(cs); + + /* emit DISCONNECT_B3_IND */ + command = CAPI_DISCONNECT_B3; + msgsize = CAPI_DISCONNECT_B3_IND_BASELEN; + } else { + /* + * Accept: emit CONNECT_B3_ACTIVE_IND immediately, as + * we only send CONNECT_B3_IND if the B channel is up + */ + command = CAPI_CONNECT_B3_ACTIVE; + msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; + } + capi_cmsg_header(&iif->acmsg, ap->id, command, CAPI_IND, + ap->nextMessageNumber++, iif->acmsg.adr.adrNCCI); + __skb_trim(skb, msgsize); + capi_cmsg2message(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, skb); +} + +/* + * process DISCONNECT_REQ message + * schedule EV_HUP and emit DISCONNECT_B3_IND if necessary, + * emit DISCONNECT_CONF reply + */ +static void do_disconnect_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + struct bc_state *bcs; + _cmsg *b3cmsg; + struct sk_buff *b3skb; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number from PLCI */ + channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + if (!channel || channel > cs->channels) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "DISCONNECT_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + bcs = cs->bcs + channel - 1; + + /* ToDo: process parameter: Additional info */ + ignore_cmstruct_param(cs, iif->acmsg.AdditionalInfo, + "DISCONNECT_REQ", "Additional Info"); + + /* skip if DISCONNECT_IND already sent */ + if (!ap->connected) + return; + + /* check for active logical connection */ + if (ap->connected >= APCONN_ACTIVE) { + /* + * emit DISCONNECT_B3_IND with cause 0x3301 + * use separate cmsg structure, as the content of iif->acmsg + * is still needed for creating the _CONF message + */ + b3cmsg = kmalloc(sizeof(*b3cmsg), GFP_KERNEL); + if (!b3cmsg) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, + ap->nextMessageNumber++, + iif->acmsg.adr.adrPLCI | (1 << 16)); + b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; + b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); + if (b3skb == NULL) { + dev_err(cs->dev, "%s: out of memory\n", __func__); + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + capi_cmsg2message(b3cmsg, + __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN)); + kfree(b3cmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, b3skb); + } + + /* 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 */ + send_conf(iif, ap, skb, CapiSuccess); +} + +/* + * process DISCONNECT_B3_REQ message + * schedule EV_HUP and emit DISCONNECT_B3_CONF reply + */ +static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + int channel; + + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + + /* extract and check channel number and NCCI */ + channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + if (!channel || channel > cs->channels || + ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "DISCONNECT_B3_REQ", "NCCI", iif->acmsg.adr.adrNCCI); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + + /* reject if logical connection not active */ + if (ap->connected < APCONN_ACTIVE) { + send_conf(iif, ap, skb, + CapiMessageNotSupportedInCurrentState); + return; + } + + /* 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 */ + ignore_cstruct_param(cs, iif->acmsg.NCPI, + "DISCONNECT_B3_REQ", "NCPI"); + send_conf(iif, ap, skb, + (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); +} + +/* + * process DATA_B3_REQ message + */ +static void do_data_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + struct cardstate *cs = iif->ctr.driverdata; + int channel = CAPIMSG_PLCI_PART(skb->data); + u16 ncci = CAPIMSG_NCCI_PART(skb->data); + u16 msglen = CAPIMSG_LEN(skb->data); + u16 datalen = CAPIMSG_DATALEN(skb->data); + u16 flags = CAPIMSG_FLAGS(skb->data); + + /* frequent message, avoid _cmsg overhead */ + dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data); + + gig_dbg(DEBUG_LLDATA, + "Receiving data from LL (ch: %d, flg: %x, sz: %d|%d)", + channel, flags, msglen, datalen); + + /* check parameters */ + if (channel == 0 || channel > cs->channels || ncci != 1) { + dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", + "DATA_B3_REQ", "NCCI", CAPIMSG_NCCI(skb->data)); + send_conf(iif, ap, skb, CapiIllContrPlciNcci); + return; + } + if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64) + dev_notice(cs->dev, "%s: unexpected length %d\n", + "DATA_B3_REQ", msglen); + if (msglen + datalen != skb->len) + dev_notice(cs->dev, "%s: length mismatch (%d+%d!=%d)\n", + "DATA_B3_REQ", msglen, datalen, skb->len); + if (msglen + datalen > skb->len) { + /* message too short for announced data length */ + send_conf(iif, ap, skb, CapiIllMessageParmCoding); /* ? */ + return; + } + if (flags & CAPI_FLAGS_RESERVED) { + dev_notice(cs->dev, "%s: reserved flags set (%x)\n", + "DATA_B3_REQ", flags); + send_conf(iif, ap, skb, CapiIllMessageParmCoding); + return; + } + + /* reject if logical connection not active */ + if (ap->connected < APCONN_ACTIVE) { + send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); + return; + } + + /* + * pull CAPI message from skb, + * pass payload data to device-specific module + * CAPI message will be preserved in headroom + */ + skb_pull(skb, msglen); + if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { + send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); + return; + } + + /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */ + + /* + * ToDo: honor unset "delivery confirmation" bit + * (send DATA_B3_CONF immediately?) + */ +} + +/* + * process RESET_B3_REQ message + * just always reply "not supported by current protocol" + */ +static void do_reset_b3_req(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + send_conf(iif, ap, skb, + CapiResetProcedureNotSupportedByCurrentProtocol); +} + +/* + * dump unsupported/ignored messages at most twice per minute, + * some apps send those very frequently + */ +static unsigned long ignored_msg_dump_time; + +/* + * unsupported CAPI message handler + */ +static void do_unsupported(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); +} + +/* + * CAPI message handler: no-op + */ +static void do_nothing(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) { + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + } + dev_kfree_skb(skb); +} + +static void do_data_b3_resp(struct gigaset_capi_ctr *iif, + struct gigaset_capi_appl *ap, + struct sk_buff *skb) +{ + dump_rawmsg(DEBUG_LLDATA, __func__, skb->data); + dev_kfree_skb(skb); +} + +/* table of outgoing CAPI message handlers with lookup function */ +typedef void (*capi_send_handler_t)(struct gigaset_capi_ctr *, + struct gigaset_capi_appl *, + struct sk_buff *); + +static struct { + u16 cmd; + capi_send_handler_t handler; +} capi_send_handler_table[] = { + /* most frequent messages first for faster lookup */ + { CAPI_DATA_B3_REQ, do_data_b3_req }, + { CAPI_DATA_B3_RESP, do_data_b3_resp }, + + { CAPI_ALERT_REQ, do_alert_req }, + { CAPI_CONNECT_ACTIVE_RESP, do_nothing }, + { CAPI_CONNECT_B3_ACTIVE_RESP, do_nothing }, + { CAPI_CONNECT_B3_REQ, do_connect_b3_req }, + { CAPI_CONNECT_B3_RESP, do_connect_b3_resp }, + { CAPI_CONNECT_B3_T90_ACTIVE_RESP, do_nothing }, + { CAPI_CONNECT_REQ, do_connect_req }, + { CAPI_CONNECT_RESP, do_connect_resp }, + { CAPI_DISCONNECT_B3_REQ, do_disconnect_b3_req }, + { CAPI_DISCONNECT_B3_RESP, do_nothing }, + { CAPI_DISCONNECT_REQ, do_disconnect_req }, + { CAPI_DISCONNECT_RESP, do_nothing }, + { CAPI_FACILITY_REQ, do_facility_req }, + { CAPI_FACILITY_RESP, do_nothing }, + { CAPI_LISTEN_REQ, do_listen_req }, + { CAPI_SELECT_B_PROTOCOL_REQ, do_unsupported }, + { CAPI_RESET_B3_REQ, do_reset_b3_req }, + { CAPI_RESET_B3_RESP, do_nothing }, + + /* + * ToDo: support overlap sending (requires ev-layer state + * machine extension to generate additional ATD commands) + */ + { CAPI_INFO_REQ, do_unsupported }, + { CAPI_INFO_RESP, do_nothing }, + + /* + * ToDo: what's the proper response for these? + */ + { CAPI_MANUFACTURER_REQ, do_nothing }, + { CAPI_MANUFACTURER_RESP, do_nothing }, +}; + +/* look up handler */ +static inline capi_send_handler_t lookup_capi_send_handler(const u16 cmd) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(capi_send_handler_table); i++) + if (capi_send_handler_table[i].cmd == cmd) + return capi_send_handler_table[i].handler; + return NULL; +} + + +/** + * gigaset_send_message() - accept a CAPI message from an application + * @ctr: controller descriptor structure. + * @skb: CAPI message. + * + * Return value: CAPI error code + * Note: capidrv (and probably others, too) only uses the return value to + * decide whether it has to free the skb (only if result != CAPI_NOERROR (0)) + */ +static u16 gigaset_send_message(struct capi_ctr *ctr, struct sk_buff *skb) +{ + struct gigaset_capi_ctr *iif + = container_of(ctr, struct gigaset_capi_ctr, ctr); + struct cardstate *cs = ctr->driverdata; + struct gigaset_capi_appl *ap; + capi_send_handler_t handler; + + /* can only handle linear sk_buffs */ + if (skb_linearize(skb) < 0) { + dev_warn(cs->dev, "%s: skb_linearize failed\n", __func__); + return CAPI_MSGOSRESOURCEERR; + } + + /* retrieve application data structure */ + ap = get_appl(iif, CAPIMSG_APPID(skb->data)); + if (!ap) { + dev_notice(cs->dev, "%s: application %u not registered\n", + __func__, CAPIMSG_APPID(skb->data)); + return CAPI_ILLAPPNR; + } + + /* look up command */ + handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); + if (!handler) { + /* unknown/unsupported message type */ + if (printk_ratelimit()) + dev_notice(cs->dev, "%s: unsupported message %u\n", + __func__, CAPIMSG_CMD(skb->data)); + return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; + } + + /* serialize */ + if (atomic_add_return(1, &iif->sendqlen) > 1) { + /* queue behind other messages */ + skb_queue_tail(&iif->sendqueue, skb); + return CAPI_NOERROR; + } + + /* process message */ + handler(iif, ap, skb); + + /* process other messages arrived in the meantime */ + while (atomic_sub_return(1, &iif->sendqlen) > 0) { + skb = skb_dequeue(&iif->sendqueue); + if (!skb) { + /* should never happen */ + dev_err(cs->dev, "%s: send queue empty\n", __func__); + continue; + } + ap = get_appl(iif, CAPIMSG_APPID(skb->data)); + if (!ap) { + /* could that happen? */ + dev_warn(cs->dev, "%s: application %u vanished\n", + __func__, CAPIMSG_APPID(skb->data)); + continue; + } + handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); + if (!handler) { + /* should never happen */ + dev_err(cs->dev, "%s: handler %x vanished\n", + __func__, CAPIMSG_CMD(skb->data)); + continue; + } + handler(iif, ap, skb); + } + + return CAPI_NOERROR; +} + +/** + * gigaset_procinfo() - build single line description for controller + * @ctr: controller descriptor structure. + * + * Return value: pointer to generated string (null terminated) + */ +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) +{ + 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", + dev_driver_string(cs->dev), dev_name(cs->dev)); + len += sprintf(page+len, "%-16s %d\n", "id", cs->myid); + if (cs->gotfwver) + len += sprintf(page+len, "%-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"); + + switch (cs->mode) { + case M_UNKNOWN: + s = "unknown"; + break; + case M_CONFIG: + s = "config"; + break; + case M_UNIMODEM: + s = "Unimodem"; + break; + case M_CID: + s = "CID"; + break; + default: + s = "??"; + } + len += sprintf(page+len, "%-16s %s\n", "mode", s); + + switch (cs->mstate) { + case MS_UNINITIALIZED: + s = "uninitialized"; + break; + case MS_INIT: + s = "init"; + break; + case MS_LOCKED: + s = "locked"; + break; + case MS_SHUTDOWN: + s = "shutdown"; + break; + case MS_RECOVER: + s = "recover"; + break; + case MS_READY: + s = "ready"; + break; + default: + s = "??"; + } + len += sprintf(page+len, "%-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"); + + for (i = 0; i < cs->channels; i++) { + len += sprintf(page+len, "[%d]%-13s %d\n", i, "corrupted", + cs->bcs[i].corrupted); + len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_down", + cs->bcs[i].trans_down); + len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_up", + cs->bcs[i].trans_up); + len += sprintf(page+len, "[%d]%-13s %d\n", i, "chstate", + cs->bcs[i].chstate); + switch (cs->bcs[i].proto2) { + case L2_BITSYNC: + s = "bitsync"; + break; + case L2_HDLC: + s = "HDLC"; + break; + case L2_VOICE: + s = "voice"; + break; + default: + s = "??"; + } + len += sprintf(page+len, "[%d]%-13s %s\n", i, "proto2", s); + } + return len; +} + + +static struct capi_driver capi_driver_gigaset = { + .name = "gigaset", + .revision = "1.0", +}; + +/** + * gigaset_isdn_register() - register 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) +{ + 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; + strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name)); + iif->ctr.driver_name = "gigaset"; + iif->ctr.load_firmware = gigaset_load_firmware; + iif->ctr.reset_ctr = gigaset_reset_ctr; + iif->ctr.register_appl = gigaset_register_appl; + 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; + INIT_LIST_HEAD(&iif->appls); + skb_queue_head_init(&iif->sendqueue); + atomic_set(&iif->sendqlen, 0); + + /* register controller with CAPI */ + 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; + } + + cs->iif = iif; + cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN; + return 1; +} + +/** + * gigaset_isdn_unregister() - unregister from LL + * @cs: device descriptor structure. + * + * Called by main module to unregister the device from the LL. + */ +void gigaset_isdn_unregister(struct cardstate *cs) +{ + struct gigaset_capi_ctr *iif = cs->iif; + + detach_capi_ctr(&iif->ctr); + kfree(iif); + cs->iif = NULL; + unregister_capi_driver(&capi_driver_gigaset); +} diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 15dc0fc28a96..1d2ae2e05e0b 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -207,6 +207,32 @@ int gigaset_get_channel(struct bc_state *bcs) return 1; } +struct bc_state *gigaset_get_free_channel(struct cardstate *cs) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&cs->lock, flags); + if (!try_module_get(cs->driver->owner)) { + gig_dbg(DEBUG_ANY, + "could not get module for allocating channel"); + spin_unlock_irqrestore(&cs->lock, flags); + return NULL; + } + for (i = 0; i < cs->channels; ++i) + if (!cs->bcs[i].use_count) { + ++cs->bcs[i].use_count; + cs->bcs[i].busy = 1; + spin_unlock_irqrestore(&cs->lock, flags); + gig_dbg(DEBUG_ANY, "allocated channel %d", i); + return cs->bcs + i; + } + module_put(cs->driver->owner); + spin_unlock_irqrestore(&cs->lock, flags); + gig_dbg(DEBUG_ANY, "no free channel"); + return NULL; +} + void gigaset_free_channel(struct bc_state *bcs) { unsigned long flags; diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cb25d2b834b9..369927f90729 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -291,21 +291,23 @@ struct reply_t gigaset_tab_cid[] = {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}}, {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, - {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, - {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, - {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 607,607, -1, 608,-1}, - {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, - {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, - - {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, - {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, + {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, + {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, + {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, + {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, + {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, + {RSP_OK, 608, 608, -1, 609, -1}, + {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, + {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, + + {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, + {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, /* optional dialing responses */ {EV_BC_OPEN, 650,650, -1, 651,-1}, - {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}}, - {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}}, + {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, + {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, + {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, /* connect */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 1185da2dbf61..4749ef100fd3 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -191,7 +191,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define AT_PROTO 4 #define AT_TYPE 5 #define AT_HLC 6 -#define AT_NUM 7 +#define AT_CLIP 7 +/* total number */ +#define AT_NUM 8 /* variables in struct at_state_t */ #define VAR_ZSAU 0 @@ -412,6 +414,8 @@ struct bc_state { struct usb_bc_state *usb; /* usb hardware driver (m105) */ struct bas_bc_state *bas; /* usb hardware driver (base) */ } hw; + + void *ap; /* LL application structure */ }; struct cardstate { @@ -725,6 +729,7 @@ void gigaset_bcs_reinit(struct bc_state *bcs); void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, struct cardstate *cs, int cid); int gigaset_get_channel(struct bc_state *bcs); +struct bc_state *gigaset_get_free_channel(struct cardstate *cs); void gigaset_free_channel(struct bc_state *bcs); int gigaset_get_channels(struct cardstate *cs); void gigaset_free_channels(struct cardstate *cs); -- cgit v1.2.1 From ec1b4cf74c81bfd0fbe5bf62bafc86c45917e72f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 5 Oct 2009 05:58:39 +0000 Subject: net: mark net_proto_ops as const All usages of structure net_proto_ops should be declared const. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/isdn/mISDN/socket.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index feb0fa45b664..28182ed8dea1 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -808,8 +808,7 @@ mISDN_sock_create(struct net *net, struct socket *sock, int proto) return err; } -static struct -net_proto_family mISDN_sock_family_ops = { +static const struct net_proto_family mISDN_sock_family_ops = { .owner = THIS_MODULE, .family = PF_ISDN, .create = mISDN_sock_create, -- cgit v1.2.1 From 6c91191668d32ea15e6950de4ee35b6c75cf4da8 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:29:37 +0000 Subject: gigaset: CAPI module readability improvements Replace the "ignoring Additional Info" warning message by better readable ones citing the specific subparameters being ignored. Make parts of the code more readable by using a local cmsg pointer variable. Impact: readability improvement Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 144 +++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 63 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index c276a925b36f..ac0a2da1eef6 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -168,14 +168,6 @@ static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, msgname, paramname); } -static inline void ignore_cmstruct_param(struct cardstate *cs, _cmstruct param, - char *msgname, char *paramname) -{ - if (param != CAPI_DEFAULT) - dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", - msgname, paramname); -} - /* * check for legal hex digit */ @@ -1062,6 +1054,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; struct sk_buff *cskb; u8 *pparam; unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; @@ -1069,14 +1062,14 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, static u8 confparam[10]; /* max. 9 octets + length byte */ /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* * Facility Request Parameter is not decoded by capi_message2cmsg() * encoding depends on Facility Selector */ - switch (iif->acmsg.FacilitySelector) { + switch (cmsg->FacilitySelector) { case CAPI_FACILITY_DTMF: /* ToDo */ info = CapiFacilityNotSupported; confparam[0] = 2; /* length */ @@ -1093,7 +1086,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, case CAPI_FACILITY_SUPPSVC: /* decode Function parameter */ - pparam = iif->acmsg.FacilityRequestParameter; + pparam = cmsg->FacilityRequestParameter; if (pparam == NULL || *pparam < 2) { dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", "Facility Request Parameter"); @@ -1141,18 +1134,18 @@ static void do_facility_req(struct gigaset_capi_ctr *iif, } /* send FACILITY_CONF with given Info and confirmation parameter */ - capi_cmsg_answer(&iif->acmsg); - iif->acmsg.Info = info; - iif->acmsg.FacilityConfirmationParameter = confparam; + capi_cmsg_answer(cmsg); + cmsg->Info = info; + cmsg->FacilityConfirmationParameter = confparam; msgsize += confparam[0]; /* length */ cskb = alloc_skb(msgsize, GFP_ATOMIC); if (!cskb) { dev_err(cs->dev, "%s: out of memory\n", __func__); return; } - capi_cmsg2message(&iif->acmsg, __skb_put(cskb, msgsize)); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, cskb); + capi_cmsg2message(cmsg, __skb_put(cskb, msgsize)); + dump_cmsg(DEBUG_CMD, __func__, cmsg); + capi_ctr_handle_message(&iif->ctr, ap->id, cskb); } @@ -1207,8 +1200,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, u16 info; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* get free B channel & construct PLCI */ bcs = gigaset_get_free_channel(cs); @@ -1411,8 +1404,16 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, "CONNECT_REQ", "Calling pty subaddr"); ignore_cstruct_param(cs, cmsg->LLC, "CONNECT_REQ", "LLC"); - ignore_cmstruct_param(cs, cmsg->AdditionalInfo, - "CONNECT_REQ", "Additional Info"); + if (cmsg->AdditionalInfo != CAPI_DEFAULT) { + ignore_cstruct_param(cs, cmsg->BChannelinformation, + "CONNECT_REQ", "B Channel Information"); + ignore_cstruct_param(cs, cmsg->Keypadfacility, + "CONNECT_REQ", "Keypad Facility"); + ignore_cstruct_param(cs, cmsg->Useruserdata, + "CONNECT_REQ", "User-User Data"); + ignore_cstruct_param(cs, cmsg->Facilitydataarray, + "CONNECT_REQ", "Facility Data Array"); + } /* encode parameter: B channel to use */ commands[AT_ISO] = kmalloc(9, GFP_KERNEL); @@ -1458,8 +1459,8 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); dev_kfree_skb(skb); /* extract and check channel number from PLCI */ @@ -1524,8 +1525,16 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, "CONNECT_RESP", "Connected Subaddress"); ignore_cstruct_param(cs, cmsg->LLC, "CONNECT_RESP", "LLC"); - ignore_cmstruct_param(cs, cmsg->AdditionalInfo, - "CONNECT_RESP", "Additional Info"); + if (cmsg->AdditionalInfo != CAPI_DEFAULT) { + ignore_cstruct_param(cs, cmsg->BChannelinformation, + "CONNECT_RESP", "BChannel Information"); + ignore_cstruct_param(cs, cmsg->Keypadfacility, + "CONNECT_RESP", "Keypad Facility"); + ignore_cstruct_param(cs, cmsg->Useruserdata, + "CONNECT_RESP", "User-User Data"); + ignore_cstruct_param(cs, cmsg->Facilitydataarray, + "CONNECT_RESP", "Facility Data Array"); + } /* Accept call */ if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, @@ -1587,17 +1596,18 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number from PLCI */ - channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + channel = (cmsg->adr.adrPLCI >> 8) & 0xff; if (!channel || channel > cs->channels) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + "CONNECT_B3_REQ", "PLCI", cmsg->adr.adrPLCI); send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } @@ -1606,14 +1616,12 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif, ap->connected = APCONN_ACTIVE; /* build NCCI: always 1 (one B3 connection only) */ - iif->acmsg.adr.adrNCCI |= 1 << 16; + cmsg->adr.adrNCCI |= 1 << 16; /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, iif->acmsg.NCPI, - "CONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); + ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI"); + send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); } /* @@ -1628,27 +1636,28 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; - struct bc_state *bcs = NULL; + _cmsg *cmsg = &iif->acmsg; + struct bc_state *bcs; int channel; unsigned int msgsize; u8 command; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number and NCCI */ - channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + channel = (cmsg->adr.adrNCCI >> 8) & 0xff; if (!channel || channel > cs->channels || - ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_RESP", "NCCI", iif->acmsg.adr.adrNCCI); + "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI); dev_kfree_skb(skb); return; } bcs = &cs->bcs[channel-1]; - if (iif->acmsg.Reject) { + if (cmsg->Reject) { /* Reject: clear B3 connect received flag */ ap->connected = APCONN_SETUP; @@ -1673,11 +1682,11 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, command = CAPI_CONNECT_B3_ACTIVE; msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; } - capi_cmsg_header(&iif->acmsg, ap->id, command, CAPI_IND, - ap->nextMessageNumber++, iif->acmsg.adr.adrNCCI); + capi_cmsg_header(cmsg, ap->id, command, CAPI_IND, + ap->nextMessageNumber++, cmsg->adr.adrNCCI); __skb_trim(skb, msgsize); - capi_cmsg2message(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_cmsg2message(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); capi_ctr_handle_message(&iif->ctr, ap->id, skb); } @@ -1691,28 +1700,37 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; struct bc_state *bcs; _cmsg *b3cmsg; struct sk_buff *b3skb; int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number from PLCI */ - channel = (iif->acmsg.adr.adrPLCI >> 8) & 0xff; + channel = (cmsg->adr.adrPLCI >> 8) & 0xff; if (!channel || channel > cs->channels) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_REQ", "PLCI", iif->acmsg.adr.adrPLCI); + "DISCONNECT_REQ", "PLCI", cmsg->adr.adrPLCI); send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } bcs = cs->bcs + channel - 1; /* ToDo: process parameter: Additional info */ - ignore_cmstruct_param(cs, iif->acmsg.AdditionalInfo, - "DISCONNECT_REQ", "Additional Info"); + if (cmsg->AdditionalInfo != CAPI_DEFAULT) { + ignore_cstruct_param(cs, cmsg->BChannelinformation, + "DISCONNECT_REQ", "B Channel Information"); + ignore_cstruct_param(cs, cmsg->Keypadfacility, + "DISCONNECT_REQ", "Keypad Facility"); + ignore_cstruct_param(cs, cmsg->Useruserdata, + "DISCONNECT_REQ", "User-User Data"); + ignore_cstruct_param(cs, cmsg->Facilitydataarray, + "DISCONNECT_REQ", "Facility Data Array"); + } /* skip if DISCONNECT_IND already sent */ if (!ap->connected) @@ -1733,7 +1751,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, } capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, ap->nextMessageNumber++, - iif->acmsg.adr.adrPLCI | (1 << 16)); + cmsg->adr.adrPLCI | (1 << 16)); b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); if (b3skb == NULL) { @@ -1769,18 +1787,19 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, struct sk_buff *skb) { struct cardstate *cs = iif->ctr.driverdata; + _cmsg *cmsg = &iif->acmsg; int channel; /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + capi_message2cmsg(cmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, cmsg); /* extract and check channel number and NCCI */ - channel = (iif->acmsg.adr.adrNCCI >> 8) & 0xff; + channel = (cmsg->adr.adrNCCI >> 8) & 0xff; if (!channel || channel > cs->channels || - ((iif->acmsg.adr.adrNCCI >> 16) & 0xffff) != 1) { + ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_B3_REQ", "NCCI", iif->acmsg.adr.adrNCCI); + "DISCONNECT_B3_REQ", "NCCI", cmsg->adr.adrNCCI); send_conf(iif, ap, skb, CapiIllContrPlciNcci); return; } @@ -1803,11 +1822,10 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, gigaset_schedule_event(cs); /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, iif->acmsg.NCPI, + ignore_cstruct_param(cs, cmsg->NCPI, "DISCONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (iif->acmsg.NCPI && iif->acmsg.NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); + send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? + CapiNcpiNotSupportedByProtocol : CapiSuccess); } /* -- cgit v1.2.1 From 22077ebceb44f4097d4677e2a26bc1175143d647 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:29:47 +0000 Subject: gigaset: fix format string typo in CAPI dial command A missing dot lead to garbage characters being included in the dial command generated from a CAPI CONNECT_REQ message, which interestingly enough worked anyway, illustrating the resilience of the device. Impact: bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index ac0a2da1eef6..d1afac2bf650 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1254,7 +1254,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, commands[AT_DIAL] = kmalloc(l+3, GFP_KERNEL); if (!commands[AT_DIAL]) goto oom; - snprintf(commands[AT_DIAL], l+3, "D%*s\r", l, pp); + snprintf(commands[AT_DIAL], l+3, "D%.*s\r", l, pp); /* encode parameter: Calling party number */ pp = cmsg->CallingPartyNumber; -- cgit v1.2.1 From 4dd8230acd20cb456cae02696b3da2986faad258 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:29:57 +0000 Subject: gigaset: fix bad assumptions about CAPI skbuffs The CAPI interface incorrectly assumed that CAPI messages would always start at the beginning of the data buffer: fix by treating DATA_B3 messages as the link layer header to their payload data. This fix changes the way acknowledgement information is propagated through the hardware specific modules and thereby impacts the ISDN4Linux variant of the driver, too. Also some assumptions about methods not being called from interrupt context turned out to be unwarranted; fix by using dev_kfree_skb_any() wherever non-interrupt context isn't guaranteed. Impact: bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 55 ++++++++++++++++++++++------------------ drivers/isdn/gigaset/capi.c | 29 +++++++++++---------- drivers/isdn/gigaset/gigaset.h | 2 +- drivers/isdn/gigaset/i4l.c | 28 ++++++++++++++------ drivers/isdn/gigaset/isocdata.c | 6 ++--- 5 files changed, 70 insertions(+), 50 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index a25216bf475e..256fc4809c81 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -156,7 +156,7 @@ byte_stuff: /* end of frame */ gigaset_isdn_rcv_err(bcs); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ #ifdef CONFIG_GIGASET_DEBUG ++bcs->emptycount; @@ -172,7 +172,7 @@ byte_stuff: "Checksum failed, %u bytes corrupted!\n", skb->len); gigaset_isdn_rcv_err(bcs); - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } else if (likely(skb->len > 2)) { __skb_trim(skb, skb->len - 2); gigaset_skb_rcvd(bcs, skb); @@ -182,7 +182,7 @@ byte_stuff: "invalid packet size (%d)\n", skb->len); gigaset_isdn_rcv_err(bcs); } - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } } @@ -430,11 +430,11 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input); * opening and closing flags, preserving headroom data. * parameters: * skb skb containing original packet (freed upon return) - * headroom number of headroom bytes to preserve * Return value: * pointer to newly allocated skb containing the result frame + * and the original link layer header, NULL on error */ -static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) +static struct sk_buff *HDLC_Encode(struct sk_buff *skb) { struct sk_buff *hdlc_skb; __u16 fcs; @@ -456,17 +456,19 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) /* size of new buffer: original size + number of stuffing bytes * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes - * + room for acknowledgement header + * + room for link layer header */ - hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + headroom); + hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len); if (!hdlc_skb) { - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NULL; } - /* Copy acknowledgement header into new skb */ - skb_reserve(hdlc_skb, headroom); - memcpy(hdlc_skb->head, skb->head, headroom); + /* Copy link layer header into new skb */ + skb_reset_mac_header(hdlc_skb); + skb_reserve(hdlc_skb, skb->mac_len); + memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len); + hdlc_skb->mac_len = skb->mac_len; /* Add flag sequence in front of everything.. */ *(skb_put(hdlc_skb, 1)) = PPP_FLAG; @@ -497,7 +499,7 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) *(skb_put(hdlc_skb, 1)) = PPP_FLAG; - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return hdlc_skb; } @@ -506,28 +508,33 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int headroom) * preserving headroom data. * parameters: * skb skb containing original packet (freed upon return) - * headroom number of headroom bytes to preserve * Return value: * pointer to newly allocated skb containing the result frame + * and the original link layer header, NULL on error */ -static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) +static struct sk_buff *iraw_encode(struct sk_buff *skb) { struct sk_buff *iraw_skb; unsigned char c; unsigned char *cp; int len; - /* worst case: every byte must be stuffed */ - iraw_skb = dev_alloc_skb(2*skb->len + headroom); + /* size of new buffer (worst case = every byte must be stuffed): + * 2 * original size + room for link layer header + */ + iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len); if (!iraw_skb) { - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return NULL; } - /* Copy acknowledgement header into new skb */ - skb_reserve(iraw_skb, headroom); - memcpy(iraw_skb->head, skb->head, headroom); + /* copy link layer header into new skb */ + skb_reset_mac_header(iraw_skb); + skb_reserve(iraw_skb, skb->mac_len); + memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len); + iraw_skb->mac_len = skb->mac_len; + /* copy and stuff data */ cp = skb->data; len = skb->len; while (len--) { @@ -536,7 +543,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) *(skb_put(iraw_skb, 1)) = c; *(skb_put(iraw_skb, 1)) = c; } - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); return iraw_skb; } @@ -548,7 +555,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int headroom) * Called by LL to encode and queue an skb for sending, and start * transmission if necessary. * Once the payload data has been transmitted completely, gigaset_skb_sent() - * will be called with the first cs->hw_hdr_len bytes of skb->head preserved. + * will be called with the skb's link layer header preserved. * * Return value: * number of bytes accepted for sending (skb->len) if ok, @@ -560,9 +567,9 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) unsigned long flags; if (bcs->proto2 == L2_HDLC) - skb = HDLC_Encode(skb, bcs->cs->hw_hdr_len); + skb = HDLC_Encode(skb); else - skb = iraw_encode(skb, bcs->cs->hw_hdr_len); + skb = iraw_encode(skb); if (!skb) { dev_err(bcs->cs->dev, "unable to allocate memory for encoding!\n"); diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index d1afac2bf650..3f5cd06af104 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -362,6 +362,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 +381,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 +394,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 +438,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; } @@ -1461,7 +1462,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; @@ -1652,7 +1653,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]; @@ -1665,7 +1666,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, 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"); @@ -1880,12 +1881,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 +1947,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 +1955,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 */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 4749ef100fd3..c59216b9c1d0 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -625,7 +625,7 @@ struct gigaset_ops { /* Called from LL interface to put an skb into the send-queue. * After sending is completed, gigaset_skb_sent() must be called - * with the first cs->hw_hdr_len bytes of skb->head preserved. */ + * with the skb's link layer header preserved. */ int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); /* Called from ev-layer.c to process a block of data diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index aca72a06184e..828824f905c4 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -41,8 +41,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack, { struct cardstate *cs; struct bc_state *bcs; + unsigned char *ack_header; unsigned len; - unsigned skblen; if (!(cs = gigaset_get_cs_by_id(driverID))) { pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); @@ -78,11 +78,23 @@ static int writebuf_from_LL(int driverID, int channel, int ack, return -EINVAL; } - skblen = ack ? len : 0; - skb->head[0] = skblen & 0xff; - skb->head[1] = skblen >> 8; - gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", - len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); + /* set up acknowledgement header */ + if (skb_headroom(skb) < HW_HDR_LEN) { + /* should never happen */ + dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__); + return -ENOMEM; + } + skb_set_mac_header(skb, -HW_HDR_LEN); + skb->mac_len = HW_HDR_LEN; + ack_header = skb_mac_header(skb); + if (ack) { + ack_header[0] = len & 0xff; + ack_header[1] = len >> 8; + } else { + ack_header[0] = ack_header[1] = 0; + } + gig_dbg(DEBUG_MCMD, "skb: len=%u, ack=%d: %02x %02x", + len, ack, ack_header[0], ack_header[1]); /* pass to device-specific module */ return cs->ops->send_skb(bcs, skb); @@ -99,6 +111,7 @@ static int writebuf_from_LL(int driverID, int channel, int ack, void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) { isdn_if *iif = bcs->cs->iif; + unsigned char *ack_header = skb_mac_header(skb); unsigned len; isdn_ctrl response; @@ -108,8 +121,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", __func__, skb->len); - len = (unsigned char) skb->head[0] | - (unsigned) (unsigned char) skb->head[1] << 8; + len = ack_header[0] + ((unsigned) ack_header[1] << 8); if (len) { gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", bcs->cs->myid, bcs->channel, len); diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 7dabfd35874c..bc41611e541d 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -576,12 +576,12 @@ static inline void hdlc_done(struct bc_state *bcs) dev_notice(cs->dev, "received short frame (%d octets)\n", procskb->len); bcs->hw.bas->runts++; - dev_kfree_skb(procskb); + dev_kfree_skb_any(procskb); gigaset_isdn_rcv_err(bcs); } else if (bcs->fcs != PPP_GOODFCS) { dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); bcs->hw.bas->fcserrs++; - dev_kfree_skb(procskb); + dev_kfree_skb_any(procskb); gigaset_isdn_rcv_err(bcs); } else { len = procskb->len; @@ -985,7 +985,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) * Called by LL to queue an skb for sending, and start transmission if * necessary. * Once the payload data has been transmitted completely, gigaset_skb_sent() - * will be called with the first cs->hw_hdr_len bytes of skb->head preserved. + * will be called with the skb's link layer header preserved. * * Return value: * number of bytes accepted for sending (skb->len) if ok, -- cgit v1.2.1 From 2032e2c2309de02cd67b1d26aa701c2a57c4639f Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:07 +0000 Subject: usb_gigaset: code cleanup Reorganize the code of the Gigaset M10x driver to make it more readable, less redundant, better aligned to the style of other parts of the driver, and cause fewer checkpatch.pl complaints. Impact: code reorganization, no functional change Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 573 ++++++++++++++++++++----------------- drivers/isdn/gigaset/common.c | 34 +-- drivers/isdn/gigaset/gigaset.h | 13 +- drivers/isdn/gigaset/usb-gigaset.c | 69 +++-- 4 files changed, 358 insertions(+), 331 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 256fc4809c81..ccb2a7b7c41d 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -19,7 +19,7 @@ /* check if byte must be stuffed/escaped * I'm not sure which data should be encoded. - * Therefore I will go the hard way and decode every value + * Therefore I will go the hard way and encode every value * less than 0x20, the flag sequence and the control escape char. */ static inline int muststuff(unsigned char c) @@ -35,288 +35,383 @@ static inline int muststuff(unsigned char c) /* == data input =========================================================== */ -/* process a block of received bytes in command mode (modem response) +/* process a block of received bytes in command mode + * (mstate != MS_LOCKED && (inputstate & INS_command)) + * Append received bytes to the command response buffer and forward them + * line by line to the response handler. Exit whenever a mode/state change + * might have occurred. * Return value: * number of processed bytes */ -static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) { + unsigned char *src = inbuf->data + inbuf->head; struct cardstate *cs = inbuf->cs; - unsigned cbytes = cs->cbytes; - int inputstate = inbuf->inputstate; - int startbytes = numbytes; - - for (;;) { - cs->respdata[cbytes] = c; - if (c == 10 || c == 13) { - gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + unsigned cbytes = cs->cbytes; + unsigned procbytes = 0; + unsigned char c; + + while (procbytes < numbytes) { + c = *src++; + procbytes++; + + switch (c) { + case '\n': + if (cbytes == 0 && cs->respdata[0] == '\r') { + /* collapse LF with preceding CR */ + cs->respdata[0] = 0; + break; + } + /* --v-- fall through --v-- */ + case '\r': + /* end of message line, pass to response handler */ + gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)", __func__, cbytes); + if (cbytes >= MAX_RESP_SIZE) { + dev_warn(cs->dev, "response too large (%d)\n", + cbytes); + cbytes = MAX_RESP_SIZE; + } cs->cbytes = cbytes; - gigaset_handle_modem_response(cs); /* can change - cs->dle */ + gigaset_handle_modem_response(cs); cbytes = 0; - if (cs->dle && - !(inputstate & INS_DLE_command)) { - inputstate &= ~INS_command; - break; - } - } else { - /* advance in line buffer, checking for overflow */ - if (cbytes < MAX_RESP_SIZE - 1) - cbytes++; - else - dev_warn(cs->dev, "response too large\n"); - } + /* store EOL byte for CRLF collapsing */ + cs->respdata[0] = c; - if (!numbytes) - break; - c = *src++; - --numbytes; - if (c == DLE_FLAG && - (cs->dle || inputstate & INS_DLE_command)) { - inputstate |= INS_DLE_char; - break; + /* cs->dle may have changed */ + if (cs->dle && !(inbuf->inputstate & INS_DLE_command)) + inbuf->inputstate &= ~INS_command; + + /* return for reevaluating state */ + goto exit; + + case DLE_FLAG: + if (inbuf->inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inbuf->inputstate &= ~INS_DLE_char; + } else if (cs->dle || + (inbuf->inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inbuf->inputstate |= INS_DLE_char; + goto exit; + } + /* quoted or not in DLE mode: treat as regular data */ + /* --v-- fall through --v-- */ + default: + /* append to line buffer if possible */ + if (cbytes < MAX_RESP_SIZE) + cs->respdata[cbytes] = c; + cbytes++; } } - +exit: cs->cbytes = cbytes; - inbuf->inputstate = inputstate; - - return startbytes - numbytes; + return procbytes; } -/* process a block of received bytes in lock mode (tty i/f) +/* process a block of received bytes in lock mode + * All received bytes are passed unmodified to the tty i/f. * Return value: * number of processed bytes */ -static inline int lock_loop(unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) { - struct cardstate *cs = inbuf->cs; - - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", - numbytes, src); - gigaset_if_receive(cs, src, numbytes); + unsigned char *src = inbuf->data + inbuf->head; + gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src); + gigaset_if_receive(inbuf->cs, src, numbytes); return numbytes; } +/* set up next receive skb for data mode + */ +static void new_rcv_skb(struct bc_state *bcs) +{ + struct cardstate *cs = bcs->cs; + unsigned short hw_hdr_len = cs->hw_hdr_len; + + if (bcs->ignore) { + bcs->skb = NULL; + return; + } + + bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len); + if (bcs->skb == NULL) { + dev_warn(cs->dev, "could not allocate new skb\n"); + return; + } + skb_reserve(bcs->skb, hw_hdr_len); +} + /* process a block of received bytes in HDLC data mode + * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. * When a frame is complete, check the FCS and pass valid frames to the LL. * If DLE is encountered, return immediately to let the caller handle it. * Return value: * number of processed bytes - * numbytes (all bytes processed) on error --FIXME */ -static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = inbuf->bcs; + struct bc_state *bcs = cs->bcs; int inputstate = bcs->inputstate; __u16 fcs = bcs->fcs; struct sk_buff *skb = bcs->skb; - int startbytes = numbytes; + unsigned char *src = inbuf->data + inbuf->head; + unsigned procbytes = 0; + unsigned char c; - if (unlikely(inputstate & INS_byte_stuff)) { + if (inputstate & INS_byte_stuff) { + if (!numbytes) + return 0; inputstate &= ~INS_byte_stuff; goto byte_stuff; } - for (;;) { - if (unlikely(c == PPP_ESCAPE)) { - if (unlikely(!numbytes)) { - inputstate |= INS_byte_stuff; + + while (procbytes < numbytes) { + c = *src++; + procbytes++; + if (c == DLE_FLAG) { + if (inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inputstate &= ~INS_DLE_char; + } else if (cs->dle || (inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inputstate |= INS_DLE_char; break; } - c = *src++; - --numbytes; - if (unlikely(c == DLE_FLAG && - (cs->dle || - inbuf->inputstate & INS_DLE_command))) { - inbuf->inputstate |= INS_DLE_char; + } + + if (c == PPP_ESCAPE) { + /* byte stuffing indicator: pull in next byte */ + if (procbytes >= numbytes) { + /* end of buffer, save for later processing */ inputstate |= INS_byte_stuff; break; } byte_stuff: + c = *src++; + procbytes++; + if (c == DLE_FLAG) { + if (inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inputstate &= ~INS_DLE_char; + } else if (cs->dle || + (inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inputstate |= + INS_DLE_char | INS_byte_stuff; + break; + } + } c ^= PPP_TRANS; - if (unlikely(!muststuff(c))) - gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); - } else if (unlikely(c == PPP_FLAG)) { - if (unlikely(inputstate & INS_skip_frame)) { #ifdef CONFIG_GIGASET_DEBUG - if (!(inputstate & INS_have_data)) { /* 7E 7E */ - ++bcs->emptycount; - } else - gig_dbg(DEBUG_HDLC, - "7e----------------------------"); -#endif - - /* end of frame */ - gigaset_isdn_rcv_err(bcs); - dev_kfree_skb_any(skb); - } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ -#ifdef CONFIG_GIGASET_DEBUG - ++bcs->emptycount; + if (!muststuff(c)) + gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); #endif - break; - } else { + } else if (c == PPP_FLAG) { + /* end of frame: process content if any */ + if (inputstate & INS_have_data) { gig_dbg(DEBUG_HDLC, "7e----------------------------"); - /* end of frame */ - if (unlikely(fcs != PPP_GOODFCS)) { + /* check and pass received frame */ + if (!skb) { + /* skipped frame */ + gigaset_isdn_rcv_err(bcs); + } else if (skb->len < 2) { + /* frame too short for FCS */ + dev_warn(cs->dev, + "short frame (%d)\n", + skb->len); + gigaset_isdn_rcv_err(bcs); + dev_kfree_skb_any(skb); + } else if (fcs != PPP_GOODFCS) { + /* frame check error */ dev_err(cs->dev, "Checksum failed, %u bytes corrupted!\n", skb->len); gigaset_isdn_rcv_err(bcs); dev_kfree_skb_any(skb); - } else if (likely(skb->len > 2)) { + } else { + /* good frame */ __skb_trim(skb, skb->len - 2); gigaset_skb_rcvd(bcs, skb); - } else { - if (skb->len) { - dev_err(cs->dev, - "invalid packet size (%d)\n", skb->len); - gigaset_isdn_rcv_err(bcs); - } - dev_kfree_skb_any(skb); } - } - fcs = PPP_INITFCS; - inputstate &= ~(INS_have_data | INS_skip_frame); - if (unlikely(bcs->ignore)) { - inputstate |= INS_skip_frame; - skb = NULL; + /* prepare reception of next frame */ + inputstate &= ~INS_have_data; + new_rcv_skb(bcs); + skb = bcs->skb; } else { - skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); - if (skb != NULL) { - skb_reserve(skb, cs->hw_hdr_len); - } else { - dev_warn(cs->dev, - "could not allocate new skb\n"); - inputstate |= INS_skip_frame; + /* empty frame (7E 7E) */ +#ifdef CONFIG_GIGASET_DEBUG + ++bcs->emptycount; +#endif + if (!skb) { + /* skipped (?) */ + gigaset_isdn_rcv_err(bcs); + new_rcv_skb(bcs); + skb = bcs->skb; } } - break; - } else if (unlikely(muststuff(c))) { + fcs = PPP_INITFCS; + continue; +#ifdef CONFIG_GIGASET_DEBUG + } else if (muststuff(c)) { /* Should not happen. Possible after ZDLE=1. */ gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); +#endif } - /* add character */ - + /* regular data byte, append to skb */ #ifdef CONFIG_GIGASET_DEBUG - if (unlikely(!(inputstate & INS_have_data))) { + if (!(inputstate & INS_have_data)) { gig_dbg(DEBUG_HDLC, "7e (%d x) ================", bcs->emptycount); bcs->emptycount = 0; } #endif - inputstate |= INS_have_data; - - if (likely(!(inputstate & INS_skip_frame))) { - if (unlikely(skb->len == SBUFSIZE)) { + if (skb) { + if (skb->len == SBUFSIZE) { dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); - skb = NULL; - inputstate |= INS_skip_frame; - break; + /* skip remainder of packet */ + bcs->skb = skb = NULL; + } else { + *__skb_put(skb, 1) = c; + fcs = crc_ccitt_byte(fcs, c); } - *__skb_put(skb, 1) = c; - fcs = crc_ccitt_byte(fcs, c); - } - - if (unlikely(!numbytes)) - break; - c = *src++; - --numbytes; - if (unlikely(c == DLE_FLAG && - (cs->dle || - inbuf->inputstate & INS_DLE_command))) { - inbuf->inputstate |= INS_DLE_char; - break; } } + bcs->inputstate = inputstate; bcs->fcs = fcs; - bcs->skb = skb; - return startbytes - numbytes; + return procbytes; } /* process a block of received bytes in transparent data mode + * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC) * Invert bytes, undoing byte stuffing and watching for DLE escapes. * If DLE is encountered, return immediately to let the caller handle it. * Return value: * number of processed bytes - * numbytes (all bytes processed) on error --FIXME */ -static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) +static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = inbuf->bcs; + struct bc_state *bcs = cs->bcs; int inputstate = bcs->inputstate; struct sk_buff *skb = bcs->skb; - int startbytes = numbytes; + unsigned char *src = inbuf->data + inbuf->head; + unsigned procbytes = 0; + unsigned char c; - for (;;) { - /* add character */ - inputstate |= INS_have_data; + if (!skb) { + /* skip this block */ + new_rcv_skb(bcs); + return numbytes; + } - if (likely(!(inputstate & INS_skip_frame))) { - if (unlikely(skb->len == SBUFSIZE)) { - //FIXME just pass skb up and allocate a new one - dev_warn(cs->dev, "received packet too long\n"); - dev_kfree_skb_any(skb); - skb = NULL; - inputstate |= INS_skip_frame; + while (procbytes < numbytes && skb->len < SBUFSIZE) { + c = *src++; + procbytes++; + + if (c == DLE_FLAG) { + if (inputstate & INS_DLE_char) { + /* quoted DLE: clear quote flag */ + inputstate &= ~INS_DLE_char; + } else if (cs->dle || (inputstate & INS_DLE_command)) { + /* DLE escape, pass up for handling */ + inputstate |= INS_DLE_char; break; } - *__skb_put(skb, 1) = bitrev8(c); } - if (unlikely(!numbytes)) - break; - c = *src++; - --numbytes; - if (unlikely(c == DLE_FLAG && - (cs->dle || - inbuf->inputstate & INS_DLE_command))) { - inbuf->inputstate |= INS_DLE_char; - break; - } + /* regular data byte: append to current skb */ + inputstate |= INS_have_data; + *__skb_put(skb, 1) = bitrev8(c); } /* pass data up */ - if (likely(inputstate & INS_have_data)) { - if (likely(!(inputstate & INS_skip_frame))) { - gigaset_skb_rcvd(bcs, skb); - } - inputstate &= ~(INS_have_data | INS_skip_frame); - if (unlikely(bcs->ignore)) { - inputstate |= INS_skip_frame; - skb = NULL; - } else { - skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); - if (skb != NULL) { - skb_reserve(skb, cs->hw_hdr_len); - } else { - dev_warn(cs->dev, - "could not allocate new skb\n"); - inputstate |= INS_skip_frame; + if (inputstate & INS_have_data) { + gigaset_skb_rcvd(bcs, skb); + inputstate &= ~INS_have_data; + new_rcv_skb(bcs); + } + + bcs->inputstate = inputstate; + return procbytes; +} + +/* process DLE escapes + * Called whenever a DLE sequence might be encountered in the input stream. + * Either processes the entire DLE sequence or, if that isn't possible, + * notes the fact that an initial DLE has been received in the INS_DLE_char + * inputstate flag and resumes processing of the sequence on the next call. + */ +static void handle_dle(struct inbuf_t *inbuf) +{ + struct cardstate *cs = inbuf->cs; + + if (cs->mstate == MS_LOCKED) + return; /* no DLE processing in lock mode */ + + if (!(inbuf->inputstate & INS_DLE_char)) { + /* no DLE pending */ + if (inbuf->data[inbuf->head] == DLE_FLAG && + (cs->dle || inbuf->inputstate & INS_DLE_command)) { + /* start of DLE sequence */ + inbuf->head++; + if (inbuf->head == inbuf->tail || + inbuf->head == RBUFSIZE) { + /* end of buffer, save for later processing */ + inbuf->inputstate |= INS_DLE_char; + return; } + } else { + /* regular data byte */ + return; } } - bcs->inputstate = inputstate; - bcs->skb = skb; - return startbytes - numbytes; + /* consume pending DLE */ + inbuf->inputstate &= ~INS_DLE_char; + + switch (inbuf->data[inbuf->head]) { + case 'X': /* begin of event message */ + if (inbuf->inputstate & INS_command) + dev_notice(cs->dev, + "received X in command mode\n"); + inbuf->inputstate |= INS_command | INS_DLE_command; + inbuf->head++; /* byte consumed */ + break; + case '.': /* end of event message */ + if (!(inbuf->inputstate & INS_DLE_command)) + dev_notice(cs->dev, + "received . without X\n"); + inbuf->inputstate &= ~INS_DLE_command; + /* return to data mode if in DLE mode */ + if (cs->dle) + inbuf->inputstate &= ~INS_command; + inbuf->head++; /* byte consumed */ + break; + case DLE_FLAG: /* DLE in data stream */ + /* mark as quoted */ + inbuf->inputstate |= INS_DLE_char; + if (!(cs->dle || inbuf->inputstate & INS_DLE_command)) + dev_notice(cs->dev, + "received not in DLE mode\n"); + break; /* quoted byte left in buffer */ + default: + dev_notice(cs->dev, "received <%02x>\n", + inbuf->data[inbuf->head]); + /* quoted byte left in buffer */ + } } /** @@ -330,94 +425,39 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, */ void gigaset_m10x_input(struct inbuf_t *inbuf) { - struct cardstate *cs; - unsigned tail, head, numbytes; - unsigned char *src, c; - int procbytes; - - head = inbuf->head; - tail = inbuf->tail; - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - - if (head != tail) { - cs = inbuf->cs; - src = inbuf->data + head; - numbytes = (head > tail ? RBUFSIZE : tail) - head; - gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); + struct cardstate *cs = inbuf->cs; + unsigned numbytes, procbytes; - while (numbytes) { - if (cs->mstate == MS_LOCKED) { - procbytes = lock_loop(src, numbytes, inbuf); - src += procbytes; - numbytes -= procbytes; - } else { - c = *src++; - --numbytes; - if (c == DLE_FLAG && (cs->dle || - inbuf->inputstate & INS_DLE_command)) { - if (!(inbuf->inputstate & INS_DLE_char)) { - inbuf->inputstate |= INS_DLE_char; - goto nextbyte; - } - /* => in data stream */ - inbuf->inputstate &= ~INS_DLE_char; - } + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail); - if (!(inbuf->inputstate & INS_DLE_char)) { - - /* FIXME use function pointers? */ - if (inbuf->inputstate & INS_command) - procbytes = cmd_loop(c, src, numbytes, inbuf); - else if (inbuf->bcs->proto2 == L2_HDLC) - procbytes = hdlc_loop(c, src, numbytes, inbuf); - else - procbytes = iraw_loop(c, src, numbytes, inbuf); - - src += procbytes; - numbytes -= procbytes; - } else { /* DLE char */ - inbuf->inputstate &= ~INS_DLE_char; - switch (c) { - case 'X': /*begin of command*/ - if (inbuf->inputstate & INS_command) - dev_warn(cs->dev, - "received 'X' in command mode\n"); - inbuf->inputstate |= - INS_command | INS_DLE_command; - break; - case '.': /*end of command*/ - if (!(inbuf->inputstate & INS_command)) - dev_warn(cs->dev, - "received '.' in hdlc mode\n"); - inbuf->inputstate &= cs->dle ? - ~(INS_DLE_command|INS_command) - : ~INS_DLE_command; - break; - //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */ - default: - dev_err(cs->dev, - "received 0x10 0x%02x!\n", - (int) c); - /* FIXME: reset driver?? */ - } - } - } -nextbyte: - if (!numbytes) { - /* end of buffer, check for wrap */ - if (head > tail) { - head = 0; - src = inbuf->data; - numbytes = tail; - } else { - head = tail; - break; - } - } - } + while (inbuf->head != inbuf->tail) { + /* check for DLE escape */ + handle_dle(inbuf); - gig_dbg(DEBUG_INTR, "setting head to %u", head); - inbuf->head = head; + /* process a contiguous block of bytes */ + numbytes = (inbuf->head > inbuf->tail ? + RBUFSIZE : inbuf->tail) - inbuf->head; + gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); + /* + * numbytes may be 0 if handle_dle() ate the last byte. + * This does no harm, *_loop() will just return 0 immediately. + */ + + if (cs->mstate == MS_LOCKED) + procbytes = lock_loop(numbytes, inbuf); + else if (inbuf->inputstate & INS_command) + procbytes = cmd_loop(numbytes, inbuf); + else if (cs->bcs->proto2 == L2_HDLC) + procbytes = hdlc_loop(numbytes, inbuf); + else + procbytes = iraw_loop(numbytes, inbuf); + inbuf->head += procbytes; + + /* check for buffer wraparound */ + if (inbuf->head >= RBUFSIZE) + inbuf->head = 0; + + gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head); } } EXPORT_SYMBOL_GPL(gigaset_m10x_input); @@ -563,6 +603,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb) */ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) { + struct cardstate *cs = bcs->cs; unsigned len = skb->len; unsigned long flags; @@ -571,16 +612,16 @@ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) else skb = iraw_encode(skb); if (!skb) { - dev_err(bcs->cs->dev, + dev_err(cs->dev, "unable to allocate memory for encoding!\n"); return -ENOMEM; } skb_queue_tail(&bcs->squeue, skb); - spin_lock_irqsave(&bcs->cs->lock, flags); - if (bcs->cs->connected) - tasklet_schedule(&bcs->cs->write_tasklet); - spin_unlock_irqrestore(&bcs->cs->lock, flags); + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) + tasklet_schedule(&cs->write_tasklet); + spin_unlock_irqrestore(&cs->lock, flags); return len; /* ok so far */ } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 1d2ae2e05e0b..690ac74c82a8 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -400,9 +400,9 @@ static void gigaset_freebcs(struct bc_state *bcs) gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); clear_at_state(&bcs->at_state); gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; - if (bcs->skb) - dev_kfree_skb(bcs->skb); for (i = 0; i < AT_NUM; ++i) { kfree(bcs->commands[i]); bcs->commands[i] = NULL; @@ -560,16 +560,13 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, } -static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, - struct cardstate *cs, int inputstate) +static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs) /* inbuf->read must be allocated before! */ { inbuf->head = 0; inbuf->tail = 0; inbuf->cs = cs; - inbuf->bcs = bcs; /*base driver: NULL*/ - inbuf->rcvbuf = NULL; - inbuf->inputstate = inputstate; + inbuf->inputstate = INS_command; } /** @@ -644,16 +641,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->fcs = PPP_INITFCS; bcs->inputstate = 0; if (cs->ignoreframes) { - bcs->inputstate |= INS_skip_frame; bcs->skb = NULL; } else { bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (bcs->skb != NULL) skb_reserve(bcs->skb, cs->hw_hdr_len); - else { + else pr_err("out of memory\n"); - bcs->inputstate |= INS_skip_frame; - } } bcs->channel = channel; @@ -674,8 +668,8 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, gig_dbg(DEBUG_INIT, " failed"); gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); - if (bcs->skb) - dev_kfree_skb(bcs->skb); + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; return NULL; } @@ -764,10 +758,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->cbytes = 0; gig_dbg(DEBUG_INIT, "setting up inbuf"); - if (onechannel) { //FIXME distinction necessary? - gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); - } else - gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); + gigaset_inbuf_init(cs->inbuf, cs); cs->connected = 0; cs->isdn_up = 0; @@ -854,9 +845,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs) bcs->chstate = 0; bcs->ignore = cs->ignoreframes; - if (bcs->ignore) - bcs->inputstate |= INS_skip_frame; - + if (bcs->ignore) { + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; + } cs->ops->reinitbcshw(bcs); } @@ -877,8 +869,6 @@ static void cleanup_cs(struct cardstate *cs) free_strings(&cs->at_state); gigaset_at_init(&cs->at_state, NULL, cs, 0); - kfree(cs->inbuf->rcvbuf); - cs->inbuf->rcvbuf = NULL; cs->inbuf->inputstate = INS_command; cs->inbuf->head = 0; cs->inbuf->tail = 0; diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index c59216b9c1d0..18bff9f80727 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -223,12 +223,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define EV_BC_CLOSED -118 /* input state */ -#define INS_command 0x0001 -#define INS_DLE_char 0x0002 +#define INS_command 0x0001 /* receiving messages (not payload data) */ +#define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */ #define INS_byte_stuff 0x0004 #define INS_have_data 0x0008 -#define INS_skip_frame 0x0010 -#define INS_DLE_command 0x0020 +#define INS_DLE_command 0x0020 /* DLE message start ( X) received */ #define INS_flag_hunt 0x0040 /* channel state */ @@ -290,8 +289,6 @@ extern struct reply_t gigaset_tab_cid[]; extern struct reply_t gigaset_tab_nocid[]; struct inbuf_t { - unsigned char *rcvbuf; /* usb-gigaset receive buffer */ - struct bc_state *bcs; struct cardstate *cs; int inputstate; int head, tail; @@ -483,8 +480,8 @@ struct cardstate { struct timer_list timer; int retry_count; - int dle; /* !=0 if modem commands/responses are - dle encoded */ + int dle; /* !=0 if DLE mode is active + (ZDLE=1 received -- M10x only) */ int cur_at_seq; /* sequence of AT commands being processed */ int curchannel; /* channel those commands are meant diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4deb1ab0dbf8..f56b2a83793e 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -43,14 +43,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); #define GIGASET_MODULENAME "usb_gigaset" #define GIGASET_DEVNAME "ttyGU" -#define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256 +#define IF_WRITEBUF 2000 /* arbitrary limit */ /* Values for the Gigaset M105 Data */ #define USB_M105_VENDOR_ID 0x0681 #define USB_M105_PRODUCT_ID 0x0009 /* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table [] = { +static const struct usb_device_id gigaset_table[] = { { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). * xx is usually 0x00 but was 0x7e before starting data transfer - * in unimodem mode. So, this might be an array of characters that need - * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. + * in unimodem mode. So, this might be an array of characters that + * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. * * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two * flags per packet. @@ -114,7 +114,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); static int gigaset_resume(struct usb_interface *intf); static int gigaset_pre_reset(struct usb_interface *intf); -static struct gigaset_driver *driver = NULL; +static struct gigaset_driver *driver; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { @@ -141,6 +141,7 @@ struct usb_cardstate { struct urb *bulk_out_urb; /* Input buffer */ + unsigned char *rcvbuf; int rcvbuf_size; struct urb *read_urb; __u8 int_in_endpointAddr; @@ -164,13 +165,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, val = tiocm_to_gigaset(new_state); gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); - // don't use this in an interrupt/BH r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, (val & 0xff) | ((mask & 0xff) << 8), 0, NULL, 0, 2000 /* timeout? */); if (r < 0) return r; - //.. return 0; } @@ -220,7 +219,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) cflag &= CBAUD; switch (cflag) { - //FIXME more values? case B300: rate = 300; break; case B600: rate = 600; break; case B1200: rate = 1200; break; @@ -273,7 +271,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) /* set the number of stop bits */ if (cflag & CSTOPB) { if ((cflag & CSIZE) == CS5) - val |= 1; /* 1.5 stop bits */ //FIXME is this okay? + val |= 1; /* 1.5 stop bits */ else val |= 2; /* 2 stop bits */ } @@ -282,7 +280,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) } - /*================================================================================================================*/ +/*============================================================================*/ static int gigaset_init_bchannel(struct bc_state *bcs) { /* nothing to do for M10x */ @@ -344,7 +342,6 @@ static void gigaset_modem_fill(unsigned long data) if (write_modem(cs) < 0) { gig_dbg(DEBUG_OUTPUT, "modem_fill: write_modem failed"); - // FIXME should we tell the LL? again = 1; /* no callback will be called! */ } } @@ -356,8 +353,8 @@ static void gigaset_modem_fill(unsigned long data) */ static void gigaset_read_int_callback(struct urb *urb) { - struct inbuf_t *inbuf = urb->context; - struct cardstate *cs = inbuf->cs; + struct cardstate *cs = urb->context; + struct inbuf_t *inbuf = cs->inbuf; int status = urb->status; int r; unsigned numbytes; @@ -368,7 +365,7 @@ static void gigaset_read_int_callback(struct urb *urb) numbytes = urb->actual_length; if (numbytes) { - src = inbuf->rcvbuf; + src = cs->hw.usb->rcvbuf; if (unlikely(*src)) dev_warn(cs->dev, "%s: There was no leading 0, but 0x%02x!\n", @@ -440,7 +437,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) struct cmdbuf_t *tcb; unsigned long flags; int count; - int status = -ENOENT; // FIXME + int status = -ENOENT; struct usb_cardstate *ucs = cs->hw.usb; do { @@ -480,7 +477,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) ucs->busy = 1; spin_lock_irqsave(&cs->lock, flags); - status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; + status = cs->connected ? + usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : + -ENODEV; spin_unlock_irqrestore(&cs->lock, flags); if (status) { @@ -510,8 +509,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, if (len <= 0) return 0; - - if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); + if (!cb) { dev_err(cs->dev, "%s: out of memory\n", __func__); return -ENOMEM; } @@ -637,9 +636,7 @@ static int write_modem(struct cardstate *cs) return -EINVAL; } - /* Copy data to bulk out buffer and // FIXME copying not necessary - * transmit data - */ + /* Copy data to bulk out buffer and transmit data */ count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); skb_pull(bcs->tx_skb, count); @@ -650,7 +647,8 @@ static int write_modem(struct cardstate *cs) if (cs->connected) { usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), + ucs->bulk_out_endpointAddr & + 0x0f), ucs->bulk_out_buffer, count, gigaset_write_bulk_callback, cs); ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); @@ -666,7 +664,7 @@ static int write_modem(struct cardstate *cs) if (!bcs->tx_skb->len) { /* skb sent completely */ - gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? + gigaset_skb_sent(bcs, bcs->tx_skb); gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb); @@ -763,8 +761,8 @@ static int gigaset_probe(struct usb_interface *interface, buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); ucs->rcvbuf_size = buffer_size; ucs->int_in_endpointAddr = endpoint->bEndpointAddress; - cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); - if (!cs->inbuf[0].rcvbuf) { + ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL); + if (!ucs->rcvbuf) { dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); retval = -ENOMEM; goto error; @@ -773,9 +771,9 @@ static int gigaset_probe(struct usb_interface *interface, usb_fill_int_urb(ucs->read_urb, udev, usb_rcvintpipe(udev, endpoint->bEndpointAddress & 0x0f), - cs->inbuf[0].rcvbuf, buffer_size, + ucs->rcvbuf, buffer_size, gigaset_read_int_callback, - cs->inbuf + 0, endpoint->bInterval); + cs, endpoint->bInterval); retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); if (retval) { @@ -789,7 +787,7 @@ static int gigaset_probe(struct usb_interface *interface, if (!gigaset_start(cs)) { tasklet_kill(&cs->write_tasklet); - retval = -ENODEV; //FIXME + retval = -ENODEV; goto error; } return 0; @@ -798,11 +796,11 @@ error: usb_kill_urb(ucs->read_urb); kfree(ucs->bulk_out_buffer); usb_free_urb(ucs->bulk_out_urb); - kfree(cs->inbuf[0].rcvbuf); + kfree(ucs->rcvbuf); usb_free_urb(ucs->read_urb); usb_set_intfdata(interface, NULL); ucs->read_urb = ucs->bulk_out_urb = NULL; - cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + ucs->rcvbuf = ucs->bulk_out_buffer = NULL; usb_put_dev(ucs->udev); ucs->udev = NULL; ucs->interface = NULL; @@ -831,10 +829,10 @@ static void gigaset_disconnect(struct usb_interface *interface) kfree(ucs->bulk_out_buffer); usb_free_urb(ucs->bulk_out_urb); - kfree(cs->inbuf[0].rcvbuf); + kfree(ucs->rcvbuf); usb_free_urb(ucs->read_urb); ucs->read_urb = ucs->bulk_out_urb = NULL; - cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + ucs->rcvbuf = ucs->bulk_out_buffer = NULL; usb_put_dev(ucs->udev); ucs->interface = NULL; @@ -916,9 +914,10 @@ static int __init usb_gigaset_init(void) int result; /* allocate memory for our driver state and intialize it */ - if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE)) == NULL) + driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + GIGASET_MODULENAME, GIGASET_DEVNAME, + &ops, THIS_MODULE); + if (driver == NULL) goto error; /* register this driver with the USB subsystem */ -- cgit v1.2.1 From d9ba9c9125d89e246dc0a0702446528acceb6ddb Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:17 +0000 Subject: gigaset: checkpatch cleanup Dum sanctis checkpatch.pl'ae legibus obsequimur. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/common.c | 33 ++++++++++------------ drivers/isdn/gigaset/gigaset.h | 60 +++++++++++++++++++--------------------- drivers/isdn/gigaset/i4l.c | 29 ++++++++----------- drivers/isdn/gigaset/interface.c | 39 ++++++++++++-------------- drivers/isdn/gigaset/proc.c | 2 +- 5 files changed, 74 insertions(+), 89 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 690ac74c82a8..c438cfcb7c6d 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -108,7 +108,7 @@ int gigaset_enterconfigmode(struct cardstate *cs) { int i, r; - cs->control_state = TIOCM_RTS; //FIXME + cs->control_state = TIOCM_RTS; r = setflags(cs, TIOCM_DTR, 200); if (r < 0) @@ -132,10 +132,10 @@ int gigaset_enterconfigmode(struct cardstate *cs) error: dev_err(cs->dev, "error %d on setuartbits\n", -r); - cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? + cs->control_state = TIOCM_RTS|TIOCM_DTR; cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); - return -1; //r + return -1; } static int test_timeout(struct at_state_t *at_state) @@ -150,10 +150,9 @@ static int test_timeout(struct at_state_t *at_state) } if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - at_state->timer_index, NULL)) { - //FIXME what should we do? - } - + at_state->timer_index, NULL)) + dev_err(at_state->cs->dev, "%s: out of memory\n", + __func__); return 1; } @@ -393,9 +392,8 @@ static void gigaset_freebcs(struct bc_state *bcs) int i; gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); - if (!bcs->cs->ops->freebcshw(bcs)) { + if (!bcs->cs->ops->freebcshw(bcs)) gig_dbg(DEBUG_INIT, "failed"); - } gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); clear_at_state(&bcs->at_state); @@ -503,8 +501,6 @@ void gigaset_freecs(struct cardstate *cs) gig_dbg(DEBUG_INIT, "clearing hw"); cs->ops->freecshw(cs); - //FIXME cmdbuf - /* fall through */ case 2: /* error in initcshw */ /* Deregister from LL */ @@ -622,7 +618,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, { int i; - bcs->tx_skb = NULL; //FIXME -> hw part + bcs->tx_skb = NULL; skb_queue_head_init(&bcs->squeue); @@ -696,12 +692,13 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, int onechannel, int ignoreframes, int cidmode, const char *modulename) { - struct cardstate *cs = NULL; + struct cardstate *cs; unsigned long flags; int i; gig_dbg(DEBUG_INIT, "allocating cs"); - if (!(cs = alloc_cs(drv))) { + cs = alloc_cs(drv); + if (!cs) { pr_err("maximum number of devices exceeded\n"); return NULL; } @@ -931,15 +928,13 @@ int gigaset_start(struct cardstate *cs) cs->ops->baud_rate(cs, B115200); cs->ops->set_line_ctrl(cs, CS8); cs->control_state = TIOCM_DTR|TIOCM_RTS; - } else { - //FIXME use some saved values? } cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { cs->waiting = 0; - //FIXME what should we do? + dev_err(cs->dev, "%s: out of memory\n", __func__); goto error; } @@ -979,7 +974,7 @@ int gigaset_shutdown(struct cardstate *cs) cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { - //FIXME what should we do? + dev_err(cs->dev, "%s: out of memory\n", __func__); goto exit; } @@ -1010,7 +1005,7 @@ void gigaset_stop(struct cardstate *cs) cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { - //FIXME what should we do? + dev_err(cs->dev, "%s: out of memory\n", __func__); goto exit; } diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 18bff9f80727..3c74cd164019 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -34,8 +34,8 @@ #include #include -#define GIG_VERSION {0,5,0,0} -#define GIG_COMPAT {0,4,0,0} +#define GIG_VERSION {0, 5, 0, 0} +#define GIG_COMPAT {0, 4, 0, 0} #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ #define MAX_RESP_SIZE 512 /* Max. size of a response string */ @@ -133,35 +133,32 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) #define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) -/* int-in-events 3070 */ +/* interrupt pipe messages */ #define HD_B1_FLOW_CONTROL 0x80 #define HD_B2_FLOW_CONTROL 0x81 -#define HD_RECEIVEATDATA_ACK (0x35) // 3070 - // att: HD_RECEIVE>>AT<: "X" "." @@ -776,7 +774,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs, void *ptr, int parameter, void *arg); /* Called on CONFIG1 command from frontend. */ -int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode +int gigaset_enterconfigmode(struct cardstate *cs); /* cs->lock must not be locked */ static inline void gigaset_schedule_event(struct cardstate *cs) diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 828824f905c4..c129ee47a8fb 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -39,12 +39,12 @@ static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb) { - struct cardstate *cs; + struct cardstate *cs = gigaset_get_cs_by_id(driverID); struct bc_state *bcs; unsigned char *ack_header; unsigned len; - if (!(cs = gigaset_get_cs_by_id(driverID))) { + if (!cs) { pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); return -ENODEV; } @@ -391,22 +391,19 @@ static int command_from_LL(isdn_ctrl *cntrl) break; case ISDN_CMD_PROCEED: - gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); break; case ISDN_CMD_ALERT: - gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); if (cntrl->arg >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_ALERT: invalid channel (%d)\n", (int) cntrl->arg); return -EINVAL; } - //bcs = cs->bcs + cntrl->arg; - //bcs->proto2 = -1; - // FIXME break; case ISDN_CMD_REDIR: - gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); break; case ISDN_CMD_PROT_IO: gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); @@ -486,7 +483,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) /* fill ICALL structure */ response.parm.setup.si1 = 0; /* default: unknown */ response.parm.setup.si2 = 0; - response.parm.setup.screen = 0; //FIXME how to set these? + response.parm.setup.screen = 0; response.parm.setup.plan = 0; if (!at_state->str_var[STR_ZBC]) { /* no BC (internal call): assume speech, A-law */ @@ -507,26 +504,24 @@ int gigaset_isdn_icall(struct at_state_t *at_state) return ICALL_IGNORE; } if (at_state->str_var[STR_NMBR]) { - strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], - sizeof response.parm.setup.phone - 1); - response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0; + strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], + sizeof response.parm.setup.phone); } else response.parm.setup.phone[0] = 0; if (at_state->str_var[STR_ZCPN]) { - strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], - sizeof response.parm.setup.eazmsn - 1); - response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0; + strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], + sizeof response.parm.setup.eazmsn); } else response.parm.setup.eazmsn[0] = 0; if (!bcs) { dev_notice(cs->dev, "no channel for incoming call\n"); response.command = ISDN_STAT_ICALLW; - response.arg = 0; //FIXME + response.arg = 0; } else { gig_dbg(DEBUG_CMD, "Sending ICALL"); response.command = ISDN_STAT_ICALL; - response.arg = bcs->channel; //FIXME + response.arg = bcs->channel; } response.driver = cs->myid; retval = iif->statcallb(&response); diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 6a8e1384e7bd..577809c03aed 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -162,7 +162,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) return -ENODEV; if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; tty->driver_data = cs; ++cs->open_count; @@ -171,7 +171,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) spin_lock_irqsave(&cs->lock, flags); cs->tty = tty; spin_unlock_irqrestore(&cs->lock, flags); - tty->low_latency = 1; //FIXME test + tty->low_latency = 1; } mutex_unlock(&cs->mutex); @@ -228,7 +228,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -299,9 +299,8 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file) gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; - // FIXME read from device? retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); mutex_unlock(&cs->mutex); @@ -326,7 +325,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, cs->minor_index, __func__, set, clear); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -356,7 +355,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -390,7 +389,7 @@ static int if_write_room(struct tty_struct *tty) gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; if (!cs->connected) { gig_dbg(DEBUG_IF, "not connected"); @@ -455,9 +454,8 @@ static void if_throttle(struct tty_struct *tty) gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); - else { - //FIXME - } + else + gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -480,9 +478,8 @@ static void if_unthrottle(struct tty_struct *tty) gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); - else { - //FIXME - } + else + gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -515,10 +512,9 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old) goto out; } - // stolen from mct_u232.c iflag = tty->termios->c_iflag; cflag = tty->termios->c_cflag; - old_cflag = old ? old->c_cflag : cflag; //FIXME? + old_cflag = old ? old->c_cflag : cflag; gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index, iflag, cflag, old_cflag); @@ -632,7 +628,8 @@ void gigaset_if_receive(struct cardstate *cs, struct tty_struct *tty; spin_lock_irqsave(&cs->lock, flags); - if ((tty = cs->tty) == NULL) + tty = cs->tty; + if (tty == NULL) gig_dbg(DEBUG_ANY, "receive on closed device"); else { tty_buffer_request_room(tty, len); @@ -659,9 +656,9 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, drv->have_tty = 0; - if ((drv->tty = alloc_tty_driver(minors)) == NULL) + drv->tty = tty = alloc_tty_driver(minors); + if (tty == NULL) goto enomem; - tty = drv->tty; tty->magic = TTY_DRIVER_MAGIC, tty->major = GIG_MAJOR, @@ -676,8 +673,8 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, tty->owner = THIS_MODULE; - tty->init_termios = tty_std_termios; //FIXME - tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME + tty->init_termios = tty_std_termios; + tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_set_operations(tty, &if_ops); ret = tty_register_driver(tty); diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index 9715aad9c3f0..758a00c1d2e2 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -39,7 +39,7 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, return -EINVAL; if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; // FIXME -EINTR? + return -ERESTARTSYS; cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, -- cgit v1.2.1 From ae67d7d81436c7e85104d586562b1a220d3cd94b Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:27 +0000 Subject: ser_gigaset: checkpatch cleanup Duly uglified as demanded by checkpatch.pl. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ser-gigaset.c | 56 +++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 19 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 3071a52467ed..ac3409ea5d99 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -164,9 +164,15 @@ static void gigaset_modem_fill(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; struct bc_state *bcs; + struct sk_buff *nextskb; int sent = 0; - if (!cs || !(bcs = cs->bcs)) { + if (!cs) { + gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); + return; + } + bcs = cs->bcs; + if (!bcs) { gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); return; } @@ -179,9 +185,11 @@ static void gigaset_modem_fill(unsigned long data) return; /* no command to send; get skb */ - if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue))) + nextskb = skb_dequeue(&bcs->squeue); + if (!nextskb) /* no skb either, nothing to do */ return; + bcs->tx_skb = nextskb; gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", (unsigned long) bcs->tx_skb); @@ -236,19 +244,20 @@ static void flush_send_queue(struct cardstate *cs) * number of bytes queued, or error code < 0 */ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, - int len, struct tasklet_struct *wake_tasklet) + int len, struct tasklet_struct *wake_tasklet) { struct cmdbuf_t *cb; unsigned long flags; gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", len, buf); + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf); if (len <= 0) return 0; - if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); + if (!cb) { dev_err(cs->dev, "%s: out of memory!\n", __func__); return -ENOMEM; } @@ -392,7 +401,6 @@ static void gigaset_device_release(struct device *dev) struct platform_device *pdev = to_platform_device(dev); /* adapted from platform_device_release() in drivers/base/platform.c */ - //FIXME is this actually necessary? kfree(dev->platform_data); kfree(pdev->resource); } @@ -404,16 +412,20 @@ static void gigaset_device_release(struct device *dev) static int gigaset_initcshw(struct cardstate *cs) { int rc; + struct ser_cardstate *scs; - if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) { + scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL); + if (!scs) { pr_err("out of memory\n"); return 0; } + cs->hw.ser = scs; cs->hw.ser->dev.name = GIGASET_MODULENAME; cs->hw.ser->dev.id = cs->minor_index; cs->hw.ser->dev.dev.release = gigaset_device_release; - if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) { + rc = platform_device_register(&cs->hw.ser->dev); + if (rc != 0) { pr_err("error %d registering platform device\n", rc); kfree(cs->hw.ser); cs->hw.ser = NULL; @@ -422,7 +434,7 @@ static int gigaset_initcshw(struct cardstate *cs) dev_set_drvdata(&cs->hw.ser->dev.dev, cs); tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + &gigaset_modem_fill, (unsigned long) cs); return 1; } @@ -434,7 +446,8 @@ static int gigaset_initcshw(struct cardstate *cs) * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c * and by "if_lock" and "if_termios" in interface.c */ -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state) +static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, + unsigned new_state) { struct tty_struct *tty = cs->hw.ser->tty; unsigned int set, clear; @@ -520,8 +533,8 @@ gigaset_tty_open(struct tty_struct *tty) } /* allocate memory for our device state and intialize it */ - if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode, - GIGASET_MODULENAME))) + cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); + if (!cs) goto error; cs->dev = &cs->hw.ser->dev.dev; @@ -690,7 +703,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, if (!cs) return; - if (!(inbuf = cs->inbuf)) { + inbuf = cs->inbuf; + if (!inbuf) { dev_err(cs->dev, "%s: no inbuf\n", __func__); cs_put(cs); return; @@ -770,18 +784,21 @@ static int __init ser_gigaset_init(void) int rc; gig_dbg(DEBUG_INIT, "%s", __func__); - if ((rc = platform_driver_register(&device_driver)) != 0) { + rc = platform_driver_register(&device_driver); + if (rc != 0) { pr_err("error %d registering platform driver\n", rc); return rc; } /* allocate memory for our driver state and intialize it */ - if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE))) + &ops, THIS_MODULE); + if (!driver) goto error; - if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) { + rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc); + if (rc != 0) { pr_err("error %d registering line discipline\n", rc); goto error; } @@ -808,7 +825,8 @@ static void __exit ser_gigaset_exit(void) driver = NULL; } - if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0) + rc = tty_unregister_ldisc(N_GIGASET_M101); + if (rc != 0) pr_err("error %d unregistering line discipline\n", rc); platform_driver_unregister(&device_driver); -- cgit v1.2.1 From 7891adf18ad9658950e532b840f1d84d8ac6cce2 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:37 +0000 Subject: bas_gigaset: checkpatch cleanup On the quest for the holy grail of checkpatch.pl silence. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 68 +++++++++++++---------- drivers/isdn/gigaset/isocdata.c | 107 ++++++++++++++++++------------------- 2 files changed, 93 insertions(+), 82 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 388e63a8ae94..9fd19db045fb 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -57,7 +57,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); #define USB_SX353_PRODUCT_ID 0x0022 /* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table [] = { +static const struct usb_device_id gigaset_table[] = { { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, @@ -137,7 +137,7 @@ struct bas_cardstate { #define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ -static struct gigaset_driver *driver = NULL; +static struct gigaset_driver *driver; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { @@ -601,11 +601,12 @@ static int atread_submit(struct cardstate *cs, int timeout) ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, usb_rcvctrlpipe(ucs->udev, 0), - (unsigned char*) & ucs->dr_cmd_in, + (unsigned char *) &ucs->dr_cmd_in, ucs->rcvbuf, ucs->rcvbuf_size, read_ctrl_callback, cs->inbuf); - if ((ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC)) != 0) { + ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC); + if (ret != 0) { update_basstate(ucs, 0, BS_ATRDPEND); dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", get_usb_rcmsg(ret)); @@ -652,13 +653,11 @@ static void read_int_callback(struct urb *urb) return; case -ENODEV: /* device removed */ case -ESHUTDOWN: /* device shut down */ - //FIXME use this as disconnect indicator? gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); return; default: /* severe trouble */ dev_warn(cs->dev, "interrupt read: %s\n", get_usb_statmsg(status)); - //FIXME corrective action? resubmission always ok? goto resubmit; } @@ -742,7 +741,8 @@ static void read_int_callback(struct urb *urb) kfree(ucs->rcvbuf); ucs->rcvbuf_size = 0; } - if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { + ucs->rcvbuf = kmalloc(l, GFP_ATOMIC); + if (ucs->rcvbuf == NULL) { spin_unlock_irqrestore(&cs->lock, flags); dev_err(cs->dev, "out of memory receiving AT data\n"); error_reset(cs); @@ -750,12 +750,12 @@ static void read_int_callback(struct urb *urb) } ucs->rcvbuf_size = l; ucs->retry_cmd_in = 0; - if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) { + rc = atread_submit(cs, BAS_TIMEOUT); + if (rc < 0) { kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; if (rc != -ENODEV) { - //FIXME corrective action? spin_unlock_irqrestore(&cs->lock, flags); error_reset(cs); break; @@ -940,7 +940,8 @@ static int starturbs(struct bc_state *bcs) } dump_urb(DEBUG_ISO, "Initial isoc read", urb); - if ((rc = usb_submit_urb(urb, GFP_ATOMIC)) != 0) + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc != 0) goto error; } @@ -1045,7 +1046,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) /* compute frame length according to flow control */ ifd->length = BAS_NORMFRAME; - if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) { + corrbytes = atomic_read(&ubc->corrbytes); + if (corrbytes != 0) { gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes); if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) @@ -1284,7 +1286,8 @@ static void read_iso_tasklet(unsigned long data) for (;;) { /* retrieve URB */ spin_lock_irqsave(&ubc->isoinlock, flags); - if (!(urb = ubc->isoindone)) { + urb = ubc->isoindone; + if (!urb) { spin_unlock_irqrestore(&ubc->isoinlock, flags); return; } @@ -1371,7 +1374,7 @@ static void read_iso_tasklet(unsigned long data) "isochronous read: %d data bytes missing\n", totleft); - error: +error: /* URB processed, resubmit */ for (frame = 0; frame < BAS_NUMFRAMES; frame++) { urb->iso_frame_desc[frame].status = 0; @@ -1568,7 +1571,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) ucs->dr_ctrl.wLength = 0; usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, usb_sndctrlpipe(ucs->udev, 0), - (unsigned char*) &ucs->dr_ctrl, NULL, 0, + (unsigned char *) &ucs->dr_ctrl, NULL, 0, write_ctrl_callback, ucs); ucs->retry_ctrl = 0; ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); @@ -1621,7 +1624,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) return -EHOSTUNREACH; } - if ((ret = starturbs(bcs)) < 0) { + ret = starturbs(bcs); + if (ret < 0) { dev_err(cs->dev, "could not start isochronous I/O for channel B%d: %s\n", bcs->channel + 1, @@ -1633,7 +1637,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) } req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; - if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { + ret = req_submit(bcs, req, 0, BAS_TIMEOUT); + if (ret < 0) { dev_err(cs->dev, "could not open channel B%d\n", bcs->channel + 1); stopurbs(bcs->hw.bas); @@ -1677,7 +1682,8 @@ static int gigaset_close_bchannel(struct bc_state *bcs) /* channel running: tell device to close it */ req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; - if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) + ret = req_submit(bcs, req, 0, BAS_TIMEOUT); + if (ret < 0) dev_err(cs->dev, "closing channel B%d failed\n", bcs->channel + 1); @@ -1703,10 +1709,12 @@ static void complete_cb(struct cardstate *cs) gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "write_command: sent %u bytes, %u left", cs->curlen, cs->cmdbytes); - if ((cs->cmdbuf = cb->next) != NULL) { + if (cb->next != NULL) { + cs->cmdbuf = cb->next; cs->cmdbuf->prev = NULL; cs->curlen = cs->cmdbuf->len; } else { + cs->cmdbuf = NULL; cs->lastcmdbuf = NULL; cs->curlen = 0; } @@ -1833,7 +1841,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) ucs->dr_cmd_out.wLength = cpu_to_le16(len); usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, usb_sndctrlpipe(ucs->udev, 0), - (unsigned char*) &ucs->dr_cmd_out, buf, len, + (unsigned char *) &ucs->dr_cmd_out, buf, len, write_command_callback, cs); rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); if (unlikely(rc)) { @@ -1953,7 +1961,8 @@ static int gigaset_write_cmd(struct cardstate *cs, if (len > IF_WRITEBUF) len = IF_WRITEBUF; - if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { + cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); + if (!cb) { dev_err(cs->dev, "%s: out of memory\n", __func__); rc = -ENOMEM; goto notqueued; @@ -2100,7 +2109,8 @@ static int gigaset_initbcshw(struct bc_state *bcs) } ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; ubc->numsub = 0; - if (!(ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL))) { + ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL); + if (!ubc->isooutbuf) { pr_err("out of memory\n"); kfree(ubc); bcs->hw.bas = NULL; @@ -2252,7 +2262,8 @@ static int gigaset_probe(struct usb_interface *interface, gig_dbg(DEBUG_ANY, "%s: wrong alternate setting %d - trying to switch", __func__, hostif->desc.bAlternateSetting); - if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) { + if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) + < 0) { dev_warn(&udev->dev, "usb_set_interface failed, " "device %d interface %d altsetting %d\n", udev->devnum, hostif->desc.bInterfaceNumber, @@ -2321,14 +2332,16 @@ static int gigaset_probe(struct usb_interface *interface, (endpoint->bEndpointAddress) & 0x0f), ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, endpoint->bInterval); - if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { + rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); + if (rc != 0) { dev_err(cs->dev, "could not submit interrupt URB: %s\n", get_usb_rcmsg(rc)); goto error; } /* tell the device that the driver is ready */ - if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) + rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0); + if (rc != 0) goto error; /* tell common part that the device is ready */ @@ -2524,9 +2537,10 @@ static int __init bas_gigaset_init(void) int result; /* allocate memory for our driver state and intialize it */ - if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &gigops, THIS_MODULE)) == NULL) + driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, + GIGASET_MODULENAME, GIGASET_DEVNAME, + &gigops, THIS_MODULE); + if (driver == NULL) goto error; /* register this driver with the USB subsystem */ diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index bc41611e541d..85394a6ebae8 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -41,7 +41,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) read = iwb->read; write = iwb->write; - if ((freebytes = read - write) > 0) { + freebytes = read - write; + if (freebytes > 0) { /* no wraparound: need padding space within regular area */ return freebytes - BAS_OUTBUFPAD; } else if (read < BAS_OUTBUFPAD) { @@ -53,29 +54,6 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) } } -/* compare two offsets within the buffer - * The buffer is seen as circular, with the read position as start - * returns -1/0/1 if position a position b without crossing 'read' - */ -static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) -{ - int read; - if (a == b) - return 0; - read = iwb->read; - if (a < b) { - if (a < read && read <= b) - return +1; - else - return -1; - } else { - if (b < read && read <= a) - return -1; - else - return +1; - } -} - /* start writing * acquire the write semaphore * return true if acquired, false if busy @@ -271,7 +249,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, * bit 14..13 = number of bits added by stuffing */ static const u16 stufftab[5 * 256] = { -// previous 1s = 0: +/* previous 1s = 0: */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, @@ -289,7 +267,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, -// previous 1s = 1: +/* previous 1s = 1: */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, @@ -307,7 +285,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, -// previous 1s = 2: +/* previous 1s = 2: */ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, @@ -325,7 +303,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, -// previous 1s = 3: +/* previous 1s = 3: */ 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, @@ -343,7 +321,7 @@ static const u16 stufftab[5 * 256] = { 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, -// previous 1s = 4: +/* previous 1s = 4: */ 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, @@ -367,7 +345,8 @@ static const u16 stufftab[5 * 256] = { * parameters: * cin input byte * ones number of trailing '1' bits in result before this step - * iwb pointer to output buffer structure (write semaphore must be held) + * iwb pointer to output buffer structure + * (write semaphore must be held) * return value: * number of trailing '1' bits in result after this step */ @@ -408,7 +387,8 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, * parameters: * in input buffer * count number of bytes in input buffer - * iwb pointer to output buffer structure (write semaphore must be held) + * iwb pointer to output buffer structure + * (write semaphore must be held) * return value: * position of end of packet in output buffer on success, * -EAGAIN if write semaphore busy or buffer full @@ -440,7 +420,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, fcs = crc_ccitt_byte(fcs, c); } - /* bitstuff and append FCS (complemented, least significant byte first) */ + /* bitstuff and append FCS + * (complemented, least significant byte first) */ fcs ^= 0xffff; ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); @@ -459,7 +440,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, * parameters: * in input buffer * count number of bytes in input buffer - * iwb pointer to output buffer structure (write semaphore must be held) + * iwb pointer to output buffer structure + * (write semaphore must be held) * return value: * position of end of packet in output buffer on success, * -EAGAIN if write semaphore busy or buffer full @@ -567,8 +549,8 @@ static inline void hdlc_done(struct bc_state *bcs) hdlc_flush(bcs); return; } - - if ((procskb = bcs->skb) == NULL) { + procskb = bcs->skb; + if (procskb == NULL) { /* previous error */ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); gigaset_isdn_rcv_err(bcs); @@ -646,8 +628,8 @@ static const unsigned char bitcounts[256] = { }; /* hdlc_unpack - * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation) - * on a sequence of received data bytes (8 bits each, LSB first) + * perform HDLC frame processing (bit unstuffing, flag detection, FCS + * calculation) on a sequence of received data bytes (8 bits each, LSB first) * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd * notify of errors via gigaset_isdn_rcv_err * tally frames, errors etc. in BC structure counters @@ -665,9 +647,12 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, /* load previous state: * inputstate = set of flag bits: - * - INS_flag_hunt: no complete opening flag received since connection setup or last abort - * - INS_have_data: at least one complete data byte received since last flag - * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7) + * - INS_flag_hunt: no complete opening flag received since connection + * setup or last abort + * - INS_have_data: at least one complete data byte received since last + * flag + * seqlen = number of consecutive '1' bits in last 7 input stream bits + * (0..7) * inbyte = accumulated partial data byte (if !INS_flag_hunt) * inbits = number of valid bits in inbyte, starting at LSB (0..6) */ @@ -701,9 +686,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, inbyte = c >> (lead1 + 1); inbits = 7 - lead1; if (trail1 >= 8) { - /* interior stuffing: omitting the MSB handles most cases */ + /* interior stuffing: + * omitting the MSB handles most cases, + * correct the incorrectly handled + * cases individually */ inbits--; - /* correct the incorrectly handled cases individually */ switch (c) { case 0xbe: inbyte = 0x3f; @@ -729,13 +716,14 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, hdlc_flush(bcs); inputstate |= INS_flag_hunt; } else if (seqlen == 6) { - /* closing flag, including (6 - lead1) '1's and one '0' from inbits */ + /* closing flag, including (6 - lead1) '1's + * and one '0' from inbits */ if (inbits > 7 - lead1) { hdlc_frag(bcs, inbits + lead1 - 7); inputstate &= ~INS_have_data; } else { if (inbits < 7 - lead1) - ubc->stolen0s ++; + ubc->stolen0s++; if (inputstate & INS_have_data) { hdlc_done(bcs); inputstate &= ~INS_have_data; @@ -744,7 +732,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, if (c == PPP_FLAG) { /* complete flag, LSB overlaps preceding flag */ - ubc->shared0s ++; + ubc->shared0s++; inbits = 0; inbyte = 0; } else if (trail1 != 7) { @@ -752,9 +740,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, inbyte = c >> (lead1 + 1); inbits = 7 - lead1; if (trail1 >= 8) { - /* interior stuffing: omitting the MSB handles most cases */ + /* interior stuffing: + * omitting the MSB handles most cases, + * correct the incorrectly handled + * cases individually */ inbits--; - /* correct the incorrectly handled cases individually */ switch (c) { case 0xbe: inbyte = 0x3f; @@ -762,7 +752,8 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, } } } else { - /* abort sequence follows, skb already empty anyway */ + /* abort sequence follows, + * skb already empty anyway */ ubc->aborts++; inputstate |= INS_flag_hunt; } @@ -787,14 +778,17 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, } else { /* stuffed data */ if (trail1 < 7) { /* => seqlen == 5 */ - /* stuff bit at position lead1, no interior stuffing */ + /* stuff bit at position lead1, + * no interior stuffing */ unsigned char mask = (1 << lead1) - 1; c = (c & mask) | ((c & ~mask) >> 1); inbyte |= c << inbits; inbits += 7; } else if (seqlen < 5) { /* trail1 >= 8 */ - /* interior stuffing: omitting the MSB handles most cases */ - /* correct the incorrectly handled cases individually */ + /* interior stuffing: + * omitting the MSB handles most cases, + * correct the incorrectly handled + * cases individually */ switch (c) { case 0xbe: c = 0x7e; @@ -804,8 +798,9 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, inbits += 7; } else { /* seqlen == 5 && trail1 >= 8 */ - /* stuff bit at lead1 *and* interior stuffing */ - switch (c) { /* unstuff individually */ + /* stuff bit at lead1 *and* interior + * stuffing -- unstuff individually */ + switch (c) { case 0x7d: c = 0x3f; break; @@ -862,7 +857,8 @@ static inline void trans_receive(unsigned char *src, unsigned count, hdlc_flush(bcs); return; } - if (unlikely((skb = bcs->skb) == NULL)) { + skb = bcs->skb; + if (unlikely(skb == NULL)) { bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); if (!skb) { dev_err(cs->dev, "could not allocate skb\n"); @@ -895,7 +891,8 @@ static inline void trans_receive(unsigned char *src, unsigned count, } } -void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs) +void gigaset_isoc_receive(unsigned char *src, unsigned count, + struct bc_state *bcs) { switch (bcs->proto2) { case L2_HDLC: -- cgit v1.2.1 From c35a87ff6678f92b12437843e88f9c89437ed4a7 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:47 +0000 Subject: gigaset: checkpatch cleanup of ev-layer.c On more step towards the holy grail of checkpatch.pl silence. Impact: cosmetic Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ev-layer.c | 478 +++++++++++++++++++--------------------- 1 file changed, 231 insertions(+), 247 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 369927f90729..a9a397519bac 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -40,8 +40,8 @@ /* Possible ASCII responses */ #define RSP_OK 0 -//#define RSP_BUSY 1 -//#define RSP_CONNECT 2 +#define RSP_BUSY 1 +#define RSP_CONNECT 2 #define RSP_ZGCI 3 #define RSP_RING 4 #define RSP_ZAOC 5 @@ -68,7 +68,6 @@ #define RSP_ZHLC (RSP_STR + STR_ZHLC) #define RSP_ERROR -1 /* ERROR */ #define RSP_WRONG_CID -2 /* unknown cid in cmd */ -//#define RSP_EMPTY -3 #define RSP_UNKNOWN -4 /* unknown response */ #define RSP_FAIL -5 /* internal error */ #define RSP_INVAL -6 /* invalid response */ @@ -76,9 +75,9 @@ #define RSP_NONE -19 #define RSP_STRING -20 #define RSP_NULL -21 -//#define RSP_RETRYFAIL -22 -//#define RSP_RETRY -23 -//#define RSP_SKIP -24 +#define RSP_RETRYFAIL -22 +#define RSP_RETRY -23 +#define RSP_SKIP -24 #define RSP_INIT -27 #define RSP_ANY -26 #define RSP_LAST -28 @@ -158,229 +157,225 @@ #define SEQ_UMMODE 11 -// 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring +/* 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), + * 400: hup, 500: reset, 600: dial, 700: ring */ struct reply_t gigaset_tab_nocid[] = { - /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ - - /* initialize device, set cid mode if possible */ - //{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}}, - //{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}}, - //{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT, - // {ACT_TIMEOUT}}, - - {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT, - {ACT_TIMEOUT}}, /* wait until device is ready */ - - {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */ - {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */ - - {EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */ - {RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */ - - {EV_TIMEOUT, 102,102, -1, 108, 5, {ACT_SETDLE1}, "^SDLE=0\r"}, /* timeout => try again in DLE mode. */ - {RSP_OK, 108,108, -1, 104,-1}, - {RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"}, - {EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}}, - {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}}, - - {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0, - ACT_HUPMODEM, - ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ - {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"}, - - {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ - {RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}}, - {RSP_ERROR, 107,107, -1, 0, 0, {ACT_FAILINIT}}, - {EV_TIMEOUT, 107,107, -1, 0, 0, {ACT_FAILINIT}}, - - {RSP_ERROR, 103,103, -1, 0, 0, {ACT_FAILINIT}}, - {EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}}, - - {RSP_STRING, 120,120, -1, 121,-1, {ACT_SETVER}}, - - {EV_TIMEOUT, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, - {RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, - {RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}}, - - /* leave dle mode */ - {RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, - {RSP_OK, 201,201, -1, 202,-1}, - {RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}}, - {RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}}, - {RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, - {EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, - - /* enter dle mode */ - {RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, - {RSP_OK, 251,251, -1, 252,-1}, - {RSP_ZDLE, 252,252, 1, 0, 0, {ACT_DLE1}}, - {RSP_ERROR, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, - {EV_TIMEOUT, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, - - /* incoming call */ - {RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}}, - - /* get cid */ - //{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}}, - //{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}}, - //{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"}, - - {RSP_INIT, 0, 0,SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, - {RSP_OK, 301,301, -1, 302,-1}, - {RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}}, - {RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}}, - {EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}}, - - /* enter cid mode */ - {RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, - {RSP_OK, 150,150, -1, 0, 0, {ACT_CMODESET}}, - {RSP_ERROR, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, - {EV_TIMEOUT, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, - - /* leave cid mode */ - //{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"}, - {RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"}, - {RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}}, - {RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, - {EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, - - /* abort getting cid */ - {RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}}, - - /* reset */ - {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, - {RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}}, - {RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, - {EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, - {RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}}, - - {EV_PROC_CIDMODE,-1, -1, -1, -1,-1, {ACT_PROC_CIDMODE}}, //FIXME - {EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME - {EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME - {EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME - {EV_STOP, -1, -1, -1, -1,-1, {ACT_STOP}}, //FIXME - {EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME - - /* misc. */ - {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, - {RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZLOG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZMWI, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZABINFO, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZSMLSTCHG,-1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - - {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, - {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, - {RSP_LAST} +/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, + * action, command */ + +/* initialize device, set cid mode if possible */ +{RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} }, + +{EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"}, +{RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING}, + "+GMR\r"}, + +{EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"}, +{RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"}, + +{EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1}, + "^SDLE=0\r"}, +{RSP_OK, 108, 108, -1, 104, -1}, +{RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"}, +{EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} }, +{RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} }, + +{EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0, + ACT_HUPMODEM, + ACT_TIMEOUT} }, +{EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"}, + +{RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"}, +{RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} }, +{RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, +{EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, + +{RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, +{EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, + +{RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} }, + +{EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER, + ACT_INIT} }, +{RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER, + ACT_INIT} }, +{RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER, + ACT_INIT} }, + +/* leave dle mode */ +{RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, +{RSP_OK, 201, 201, -1, 202, -1}, +{RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} }, +{RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} }, +{RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, +{EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, + +/* enter dle mode */ +{RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, +{RSP_OK, 251, 251, -1, 252, -1}, +{RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} }, +{RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, +{EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, + +/* incoming call */ +{RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} }, + +/* get cid */ +{RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, +{RSP_OK, 301, 301, -1, 302, -1}, +{RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} }, +{RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} }, +{EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} }, + +/* enter cid mode */ +{RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, +{RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} }, +{RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, +{EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, + +/* leave cid mode */ +{RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"}, +{RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} }, +{RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, +{EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, + +/* abort getting cid */ +{RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} }, + +/* reset */ +{RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, +{RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} }, +{RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, +{EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, +{RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} }, + +{EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} }, +{EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} }, +{EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} }, +{EV_START, -1, -1, -1, -1, -1, {ACT_START} }, +{EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} }, +{EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} }, + +/* misc. */ +{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, +{RSP_ZCFGT, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCFG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZLOG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZMWI, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZABINFO, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZSMLSTCHG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, + +{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, +{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, +{RSP_LAST} }; -// 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall +/* 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, + * 400: hup, 750: accepted icall */ struct reply_t gigaset_tab_cid[] = { - /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ - - /* dial */ - {EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME - {RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}}, - {RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}}, - {RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, - {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, - {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}}, - {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, - {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, - {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, - {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, - {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, - {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 608, 608, -1, 609, -1}, - {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, - {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, - - {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - - /* optional dialing responses */ - {EV_BC_OPEN, 650,650, -1, 651,-1}, - {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, - {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, - - /* connect */ - {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, - {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP}}, - {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, - {RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP}}, - {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, - - /* remote hangup */ - {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, - {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, - {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, - - /* hangup */ - {EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME - {RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1? - {RSP_OK, 401,401, -1, 402, 5}, - {RSP_ZVLS, 402,402, 0, 403, 5}, - {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, - {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, - {RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}}, - {EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}}, - - {EV_BC_CLOSED, 0, 0, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout - - /* ring */ - {RSP_ZBC, 700,700, -1, -1,-1, {0}}, - {RSP_ZHLC, 700,700, -1, -1,-1, {0}}, - {RSP_NMBR, 700,700, -1, -1,-1, {0}}, - {RSP_ZCPN, 700,700, -1, -1,-1, {0}}, - {RSP_ZCTP, 700,700, -1, -1,-1, {0}}, - {EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}}, - {EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, - - /*accept icall*/ - {EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME - {RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}}, - {RSP_OK, 721,721, -1, 722, 5, {ACT_CMD+AT_ISO}}, - {RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ - {RSP_OK, 723,723, -1, 724, 5, {0}}, - {RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}}, - {RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, - {EV_TIMEOUT, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, - {RSP_ZSAU, 700,729,ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT}}, - {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, - {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, - - {EV_BC_OPEN, 750,750, -1, 751,-1}, - {EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}}, - - /* B channel closed (general case) */ - {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME - - /* misc. */ - {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - {RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME - - {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, - {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, - {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, - {RSP_LAST} +/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, + * action, command */ + +/* dial */ +{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, +{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} }, +{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} }, +{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, +{RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, +{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} }, +{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} }, +{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, +{RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, +{RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, +{RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, +{RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, +{RSP_OK, 608, 608, -1, 609, -1}, +{RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, +{RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, + +{RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, +{EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, + +/* optional dialing responses */ +{EV_BC_OPEN, 650, 650, -1, 651, -1}, +{RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, +{RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} }, + +/* connect */ +{RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, +{RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP} }, +{RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, +{RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, + ACT_NOTIFY_BC_UP} }, +{EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} }, + +/* remote hangup */ +{RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} }, +{RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, +{RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, + +/* hangup */ +{EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} }, +{RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, +{RSP_OK, 401, 401, -1, 402, 5}, +{RSP_ZVLS, 402, 402, 0, 403, 5}, +{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, +{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, +{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, +{RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} }, +{EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} }, + +{EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, + +/* ring */ +{RSP_ZBC, 700, 700, -1, -1, -1, {0} }, +{RSP_ZHLC, 700, 700, -1, -1, -1, {0} }, +{RSP_NMBR, 700, 700, -1, -1, -1, {0} }, +{RSP_ZCPN, 700, 700, -1, -1, -1, {0} }, +{RSP_ZCTP, 700, 700, -1, -1, -1, {0} }, +{EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} }, +{EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, + +/*accept icall*/ +{EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} }, +{RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO} }, +{RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD+AT_ISO} }, +{RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"}, +{RSP_OK, 723, 723, -1, 724, 5, {0} }, +{RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} }, +{RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, +{EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, +{RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} }, +{RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} }, +{RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} }, + +{EV_BC_OPEN, 750, 750, -1, 751, -1}, +{EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} }, + +/* B channel closed (general case) */ +{EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} }, + +/* misc. */ +{RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCCR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZAOC, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ZCSTR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, + +{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, +{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, +{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, +{RSP_LAST} }; static const struct resp_type_t resp_type[] = { - /*{"", RSP_EMPTY, RT_NOTHING},*/ {"OK", RSP_OK, RT_NOTHING}, {"ERROR", RSP_ERROR, RT_NOTHING}, {"ZSAU", RSP_ZSAU, RT_ZSAU}, @@ -404,7 +399,7 @@ static const struct resp_type_t resp_type[] = {"ZLOG", RSP_ZLOG, RT_NOTHING}, {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, - {NULL,0,0} + {NULL, 0, 0} }; /* @@ -469,7 +464,6 @@ static int cid_of_response(char *s) if (cid < 1 || cid > 65535) return -1; /* CID out of range */ return cid; - //FIXME is ;+ at end of non-CID response really impossible? } /** @@ -613,7 +607,8 @@ void gigaset_handle_modem_response(struct cardstate *cs) break; } if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) - event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING; + event->parameter = + ZSAU_OUTGOING_CALL_PROCEEDING; else if (!strcmp(argv[curarg], "CALL_DELIVERED")) event->parameter = ZSAU_CALL_DELIVERED; else if (!strcmp(argv[curarg], "ACTIVE")) @@ -896,7 +891,8 @@ static void bchannel_up(struct bc_state *bcs) gigaset_isdn_connB(bcs); } -static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) +static void start_dial(struct at_state_t *at_state, void *data, + unsigned seq_index) { struct bc_state *bcs = at_state->bcs; struct cardstate *cs = at_state->cs; @@ -973,8 +969,6 @@ static void do_start(struct cardstate *cs) cs->isdn_up = 1; gigaset_isdn_start(cs); - // FIXME: not in locked mode - // FIXME 2: only after init sequence cs->waiting = 0; wake_up(&cs->waitqueue); @@ -1128,7 +1122,6 @@ static int do_lock(struct cardstate *cs) break; case MS_LOCKED: - //retval = -EACCES; break; default: return -EBUSY; @@ -1384,7 +1377,7 @@ static void do_action(int action, struct cardstate *cs, cs->cur_at_seq = SEQ_NONE; break; - case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ + case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */ disconnect(p_at_state); break; @@ -1458,17 +1451,6 @@ static void do_action(int action, struct cardstate *cs, __func__, at_state->ConState); cs->cur_at_seq = SEQ_NONE; break; -#ifdef CONFIG_GIGASET_DEBUG - case ACT_TEST: - { - static int count = 3; //2; //1; - *p_genresp = 1; - *p_resp_code = count ? RSP_ERROR : RSP_OK; - if (count > 0) - --count; - } - break; -#endif case ACT_DEBUG: gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", __func__, ev->type, at_state->ConState); @@ -1503,7 +1485,7 @@ static void do_action(int action, struct cardstate *cs, do_start(cs); break; - /* events from the interface */ // FIXME without ACT_xxxx? + /* events from the interface */ case ACT_IF_LOCK: cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); cs->waiting = 0; @@ -1522,7 +1504,7 @@ static void do_action(int action, struct cardstate *cs, wake_up(&cs->waitqueue); break; - /* events from the proc file system */ // FIXME without ACT_xxxx? + /* events from the proc file system */ case ACT_PROC_CIDMODE: spin_lock_irqsave(&cs->lock, flags); if (ev->parameter != cs->cidmode) { @@ -1659,7 +1641,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev) for (curact = 0; curact < MAXACT; ++curact) { /* The row tells us what we should do .. */ - do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev); + do_action(rep->action[curact], cs, bcs, &at_state, &p_command, + &genresp, &resp_code, ev); if (!at_state) break; /* may be freed after disconnect */ } @@ -1671,13 +1654,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev) if (genresp) { spin_lock_irqsave(&cs->lock, flags); - at_state->timer_expires = 0; //FIXME - at_state->timer_active = 0; //FIXME + at_state->timer_expires = 0; + at_state->timer_active = 0; spin_unlock_irqrestore(&cs->lock, flags); - gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); + gigaset_add_event(cs, at_state, resp_code, + NULL, 0, NULL); } else { /* Send command to modem if not NULL... */ - if (p_command/*rep->command*/) { + if (p_command) { if (cs->connected) send_command(cs, p_command, sendcid, cs->dle, @@ -1764,7 +1748,8 @@ static void process_command_flags(struct cardstate *cs) } } - /* only switch back to unimodem mode, if no commands are pending and no channels are up */ + /* only switch back to unimodem mode if no commands are pending and + * no channels are up */ spin_lock_irqsave(&cs->lock, flags); if (cs->at_state.pending_commands == PC_UMMODE && !cs->cidmode @@ -1823,9 +1808,8 @@ static void process_command_flags(struct cardstate *cs) if (cs->at_state.pending_commands & PC_INIT) { cs->at_state.pending_commands &= ~PC_INIT; - cs->dle = 0; //FIXME + cs->dle = 0; cs->inbuf->inputstate = INS_command; - //FIXME reset card state (or -> LOCK0)? schedule_sequence(cs, &cs->at_state, SEQ_INIT); return; } -- cgit v1.2.1 From 50e4fe91a5edbf680853b2ca37300a47ff860d63 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 25 Oct 2009 09:30:57 +0000 Subject: gigaset: convert strcmp chain to table lookup Replace the sequence of strcmp calls for interpreting ZSAU parameter strings by a table of known strings and lookup loop to improve readability. Impact: readability improvement, no functional change Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ev-layer.c | 42 ++++++++++++++++++++++++----------------- drivers/isdn/gigaset/gigaset.h | 6 ------ 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index a9a397519bac..ddeb0456d202 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -374,7 +374,11 @@ struct reply_t gigaset_tab_cid[] = }; -static const struct resp_type_t resp_type[] = +static const struct resp_type_t { + unsigned char *response; + int resp_code; + int type; +} resp_type[] = { {"OK", RSP_OK, RT_NOTHING}, {"ERROR", RSP_ERROR, RT_NOTHING}, @@ -402,6 +406,20 @@ static const struct resp_type_t resp_type[] = {NULL, 0, 0} }; +static const struct zsau_resp_t { + unsigned char *str; + int code; +} zsau_resp[] = +{ + {"OUTGOING_CALL_PROCEEDING", ZSAU_OUTGOING_CALL_PROCEEDING}, + {"CALL_DELIVERED", ZSAU_CALL_DELIVERED}, + {"ACTIVE", ZSAU_ACTIVE}, + {"DISCONNECT_IND", ZSAU_DISCONNECT_IND}, + {"NULL", ZSAU_NULL}, + {"DISCONNECT_REQ", ZSAU_DISCONNECT_REQ}, + {NULL, ZSAU_UNKNOWN} +}; + /* * Get integer from char-pointer */ @@ -480,6 +498,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) int params; int i, j; const struct resp_type_t *rt; + const struct zsau_resp_t *zr; int curarg; unsigned long flags; unsigned next, tail, head; @@ -606,25 +625,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) event->parameter = ZSAU_NONE; break; } - if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) - event->parameter = - ZSAU_OUTGOING_CALL_PROCEEDING; - else if (!strcmp(argv[curarg], "CALL_DELIVERED")) - event->parameter = ZSAU_CALL_DELIVERED; - else if (!strcmp(argv[curarg], "ACTIVE")) - event->parameter = ZSAU_ACTIVE; - else if (!strcmp(argv[curarg], "DISCONNECT_IND")) - event->parameter = ZSAU_DISCONNECT_IND; - else if (!strcmp(argv[curarg], "NULL")) - event->parameter = ZSAU_NULL; - else if (!strcmp(argv[curarg], "DISCONNECT_REQ")) - event->parameter = ZSAU_DISCONNECT_REQ; - else { - event->parameter = ZSAU_UNKNOWN; + for (zr = zsau_resp; zr->str; ++zr) + if (!strcmp(argv[curarg], zr->str)) + break; + event->parameter = zr->code; + if (!zr->str) dev_warn(cs->dev, "%s: unknown parameter %s after ZSAU\n", __func__, argv[curarg]); - } ++curarg; break; case RT_STRING: diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 3c74cd164019..e963a6c2e86d 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -357,12 +357,6 @@ struct at_state_t { struct bc_state *bcs; }; -struct resp_type_t { - unsigned char *response; - int resp_code; /* RSP_XXXX */ - int type; /* RT_XXXX */ -}; - struct event_t { int type; void *ptr, *arg; -- cgit v1.2.1 From 3f378b684453f2a028eda463ce383370545d9cc9 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 5 Nov 2009 22:18:14 -0800 Subject: net: pass kern to net_proto_family create function The generic __sock_create function has a kern argument which allows the security system to make decisions based on if a socket is being created by the kernel or by userspace. This patch passes that flag to the net_proto_family specific create function, so it can do the same thing. Signed-off-by: Eric Paris Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- drivers/isdn/mISDN/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 28182ed8dea1..fcfe17a19a61 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -779,7 +779,7 @@ base_sock_create(struct net *net, struct socket *sock, int protocol) } static int -mISDN_sock_create(struct net *net, struct socket *sock, int proto) +mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern) { int err = -EPROTONOSUPPORT; -- cgit v1.2.1 From 4a9b5e5053a184ada2e9b19aee12b6200bb8980f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 10 Nov 2009 20:30:37 -0800 Subject: speedfax: declare MODULE_FIRMWARE Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/speedfax.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/isdn') diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c index ff3a4e290da3..7726afdbb40b 100644 --- a/drivers/isdn/hardware/mISDN/speedfax.c +++ b/drivers/isdn/hardware/mISDN/speedfax.c @@ -110,6 +110,7 @@ set_debug(const char *val, struct kernel_param *kp) MODULE_AUTHOR("Karsten Keil"); MODULE_LICENSE("GPL v2"); MODULE_VERSION(SPEEDFAX_REV); +MODULE_FIRMWARE("isdn/ISAR.BIN"); module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Speedfax debug mask"); module_param(irqloops, uint, S_IRUGO | S_IWUSR); -- cgit v1.2.1 From 5452fee23eddb5ebb46f13aba50c8930c160e1da Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 19 Nov 2009 09:55:53 +0000 Subject: drivers/isdn/gigaset: tasklet_init - Remove unnecessary leading & from second arg Changed function pointer use from non-majority address-of style to majority short form without & via: grep -rPl "\btasklet_init\s*\([^,\)]+,\s*\&" drivers/isdn | while read file ; do \ perl -i -e 'local $/; while (<>) { s@(\btasklet_init\s*\([^,\)]+,\s*)\&@\1@g ; print ; }' $file ;\ done Compile tested allyesconfig x86 Signed-off-by: Joe Perches drivers/isdn/gigaset/bas-gigaset.c | 4 ++-- drivers/isdn/gigaset/common.c | 2 +- drivers/isdn/gigaset/interface.c | 2 +- drivers/isdn/gigaset/ser-gigaset.c | 2 +- drivers/isdn/gigaset/usb-gigaset.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 4 ++-- drivers/isdn/gigaset/common.c | 2 +- drivers/isdn/gigaset/interface.c | 2 +- drivers/isdn/gigaset/ser-gigaset.c | 2 +- drivers/isdn/gigaset/usb-gigaset.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/isdn') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 9fd19db045fb..95ebc5129895 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -2117,7 +2117,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) return 0; } tasklet_init(&ubc->sent_tasklet, - &write_iso_tasklet, (unsigned long) bcs); + write_iso_tasklet, (unsigned long) bcs); spin_lock_init(&ubc->isoinlock); for (i = 0; i < BAS_INURBS; ++i) @@ -2138,7 +2138,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) ubc->shared0s = 0; ubc->stolen0s = 0; tasklet_init(&ubc->rcvd_tasklet, - &read_iso_tasklet, (unsigned long) bcs); + read_iso_tasklet, (unsigned long) bcs); return 1; } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index c438cfcb7c6d..82ed1cd14ff5 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -727,7 +727,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->ev_tail = 0; cs->ev_head = 0; - tasklet_init(&cs->event_tasklet, &gigaset_handle_event, + tasklet_init(&cs->event_tasklet, gigaset_handle_event, (unsigned long) cs); cs->commands_pending = 0; cs->cur_at_seq = 0; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 577809c03aed..d2260b0055fc 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -584,7 +584,7 @@ void gigaset_if_init(struct cardstate *cs) if (!drv->have_tty) return; - tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); + tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); mutex_lock(&cs->mutex); cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ac3409ea5d99..168d585d64d8 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -434,7 +434,7 @@ static int gigaset_initcshw(struct cardstate *cs) dev_set_drvdata(&cs->hw.ser->dev.dev, cs); tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + gigaset_modem_fill, (unsigned long) cs); return 1; } diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index f56b2a83793e..3ab1daeb276b 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -614,7 +614,7 @@ static int gigaset_initcshw(struct cardstate *cs) ucs->bulk_out_urb = NULL; ucs->read_urb = NULL; tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + gigaset_modem_fill, (unsigned long) cs); return 1; } -- cgit v1.2.1