aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/capi.c
diff options
context:
space:
mode:
authorTilman Schmidt <tilman@imap.cc>2010-06-21 09:54:50 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-26 00:17:00 -0400
commit23b36778b4c82577746d26e4ac0ae66c6f462475 (patch)
treef74f7f16065c20c5f98afdba0d81f7801ff3af4a /drivers/isdn/gigaset/capi.c
parent278a582989ade4cb5335762d6c5999562018859d (diff)
isdn/gigaset: correct CAPI DATA_B3 Delivery Confirmation
The Gigaset CAPI driver handled all DATA_B3_REQ messages as if the Delivery Confirmation flag bit was set, delaying the emission of the DATA_B3_CONF reply until the data was actually transmitted. Some CAPI applications (notably Asterisk) aren't happy with that behaviour. Change it to actually evaluate the Delivery Confirmation flag as described the CAPI specification. Impact: bugfix Signed-off-by: Tilman Schmidt <tilman@imap.cc> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn/gigaset/capi.c')
-rw-r--r--drivers/isdn/gigaset/capi.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index cb55ead557cc..e685123fef48 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -320,6 +320,39 @@ static const char *format_ie(const char *ie)
320 return result; 320 return result;
321} 321}
322 322
323/*
324 * emit DATA_B3_CONF message
325 */
326static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr,
327 u16 appl, u16 msgid, int channel,
328 u16 handle, u16 info)
329{
330 struct sk_buff *cskb;
331 u8 *msg;
332
333 cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
334 if (!cskb) {
335 dev_err(cs->dev, "%s: out of memory\n", __func__);
336 return;
337 }
338 /* frequent message, avoid _cmsg overhead */
339 msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN);
340 CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN);
341 CAPIMSG_SETAPPID(msg, appl);
342 CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3);
343 CAPIMSG_SETSUBCOMMAND(msg, CAPI_CONF);
344 CAPIMSG_SETMSGID(msg, msgid);
345 CAPIMSG_SETCONTROLLER(msg, ctr->cnr);
346 CAPIMSG_SETPLCI_PART(msg, channel);
347 CAPIMSG_SETNCCI_PART(msg, 1);
348 CAPIMSG_SETHANDLE_CONF(msg, handle);
349 CAPIMSG_SETINFO_CONF(msg, info);
350
351 /* emit message */
352 dump_rawmsg(DEBUG_MCMD, __func__, msg);
353 capi_ctr_handle_message(ctr, appl, cskb);
354}
355
323 356
324/* 357/*
325 * driver interface functions 358 * driver interface functions
@@ -340,7 +373,6 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
340 struct gigaset_capi_ctr *iif = cs->iif; 373 struct gigaset_capi_ctr *iif = cs->iif;
341 struct gigaset_capi_appl *ap = bcs->ap; 374 struct gigaset_capi_appl *ap = bcs->ap;
342 unsigned char *req = skb_mac_header(dskb); 375 unsigned char *req = skb_mac_header(dskb);
343 struct sk_buff *cskb;
344 u16 flags; 376 u16 flags;
345 377
346 /* update statistics */ 378 /* update statistics */
@@ -357,34 +389,17 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
357 return; 389 return;
358 } 390 }
359 391
360 /* ToDo: honor unset "delivery confirmation" bit */ 392 /*
393 * send DATA_B3_CONF if "delivery confirmation" bit was set in request;
394 * otherwise it has already been sent by do_data_b3_req()
395 */
361 flags = CAPIMSG_FLAGS(req); 396 flags = CAPIMSG_FLAGS(req);
362 397 if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)
363 /* build DATA_B3_CONF message */ 398 send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req),
364 cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); 399 bcs->channel + 1, CAPIMSG_HANDLE_REQ(req),
365 if (!cskb) { 400 (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ?
366 dev_err(cs->dev, "%s: out of memory\n", __func__); 401 CapiFlagsNotSupportedByProtocol :
367 return; 402 CAPI_NOERROR);
368 }
369 /* frequent message, avoid _cmsg overhead */
370 CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN);
371 CAPIMSG_SETAPPID(cskb->data, ap->id);
372 CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
373 CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF);
374 CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
375 CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
376 CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
377 CAPIMSG_SETNCCI_PART(cskb->data, 1);
378 CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
379 if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
380 CAPIMSG_SETINFO_CONF(cskb->data,
381 CapiFlagsNotSupportedByProtocol);
382 else
383 CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR);
384
385 /* emit message */
386 dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data);
387 capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
388} 403}
389EXPORT_SYMBOL_GPL(gigaset_skb_sent); 404EXPORT_SYMBOL_GPL(gigaset_skb_sent);
390 405
@@ -1795,6 +1810,8 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
1795 u16 msglen = CAPIMSG_LEN(skb->data); 1810 u16 msglen = CAPIMSG_LEN(skb->data);
1796 u16 datalen = CAPIMSG_DATALEN(skb->data); 1811 u16 datalen = CAPIMSG_DATALEN(skb->data);
1797 u16 flags = CAPIMSG_FLAGS(skb->data); 1812 u16 flags = CAPIMSG_FLAGS(skb->data);
1813 u16 msgid = CAPIMSG_MSGID(skb->data);
1814 u16 handle = CAPIMSG_HANDLE_REQ(skb->data);
1798 1815
1799 /* frequent message, avoid _cmsg overhead */ 1816 /* frequent message, avoid _cmsg overhead */
1800 dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data); 1817 dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data);
@@ -1845,12 +1862,14 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
1845 return; 1862 return;
1846 } 1863 }
1847 1864
1848 /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */
1849
1850 /* 1865 /*
1851 * ToDo: honor unset "delivery confirmation" bit 1866 * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery
1852 * (send DATA_B3_CONF immediately?) 1867 * confirmation" bit is set; otherwise we have to send it now
1853 */ 1868 */
1869 if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION))
1870 send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle,
1871 flags ? CapiFlagsNotSupportedByProtocol
1872 : CAPI_NOERROR);
1854} 1873}
1855 1874
1856/* 1875/*