ircomm_lmp.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*********************************************************************
  2.  *                
  3.  * Filename:      ircomm_lmp.c
  4.  * Version:       1.0
  5.  * Description:   Interface between IrCOMM and IrLMP
  6.  * Status:        Stable
  7.  * Author:        Dag Brattli <dagb@cs.uit.no>
  8.  * Created at:    Sun Jun  6 20:48:27 1999
  9.  * Modified at:   Sun Dec 12 13:44:17 1999
  10.  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  11.  * Sources:       Previous IrLPT work by Thomas Davis
  12.  * 
  13.  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  14.  *     
  15.  *     This program is free software; you can redistribute it and/or 
  16.  *     modify it under the terms of the GNU General Public License as 
  17.  *     published by the Free Software Foundation; either version 2 of 
  18.  *     the License, or (at your option) any later version.
  19.  * 
  20.  *     This program is distributed in the hope that it will be useful,
  21.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23.  *     GNU General Public License for more details.
  24.  * 
  25.  *     You should have received a copy of the GNU General Public License 
  26.  *     along with this program; if not, write to the Free Software 
  27.  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
  28.  *     MA 02111-1307 USA
  29.  *     
  30.  ********************************************************************/
  31. #include <linux/sched.h>
  32. #include <linux/init.h>
  33. #include <net/irda/irda.h>
  34. #include <net/irda/irlmp.h>
  35. #include <net/irda/iriap.h>
  36. #include <net/irda/ircomm_event.h>
  37. #include <net/irda/ircomm_lmp.h>
  38. /*
  39.  * Function ircomm_open_lsap (self)
  40.  *
  41.  *    Open LSAP. This function will only be used when using "raw" services
  42.  *
  43.  */
  44. int ircomm_open_lsap(struct ircomm_cb *self)
  45. {
  46. notify_t notify;
  47. IRDA_DEBUG(0, __FUNCTION__ "()n");
  48.         /* Register callbacks */
  49.         irda_notify_init(&notify);
  50. notify.data_indication       = ircomm_lmp_data_indication;
  51. notify.connect_confirm       = ircomm_lmp_connect_confirm;
  52.         notify.connect_indication    = ircomm_lmp_connect_indication;
  53. notify.disconnect_indication = ircomm_lmp_disconnect_indication;
  54. notify.instance = self;
  55. strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
  56. self->lsap = irlmp_open_lsap(LSAP_ANY, &notify, 0);
  57. if (!self->lsap) {
  58. IRDA_DEBUG(0,__FUNCTION__"failed to allocate tsapn");
  59. return -1;
  60. }
  61. self->slsap_sel = self->lsap->slsap_sel;
  62. /*
  63.  *  Initialize the call-table for issuing commands
  64.  */
  65. self->issue.data_request       = ircomm_lmp_data_request;
  66. self->issue.connect_request    = ircomm_lmp_connect_request;
  67. self->issue.connect_response   = ircomm_lmp_connect_response;
  68. self->issue.disconnect_request = ircomm_lmp_disconnect_request;
  69. return 0;
  70. }
  71. /*
  72.  * Function ircomm_lmp_connect_request (self, userdata)
  73.  *
  74.  *    
  75.  *
  76.  */
  77. int ircomm_lmp_connect_request(struct ircomm_cb *self, 
  78.        struct sk_buff *userdata, 
  79.        struct ircomm_info *info)
  80. {
  81. int ret = 0;
  82. IRDA_DEBUG(0, __FUNCTION__ "()n");
  83. ret = irlmp_connect_request(self->lsap, info->dlsap_sel,
  84.     info->saddr, info->daddr, NULL, userdata); 
  85. return ret;
  86. }
  87. /*
  88.  * Function ircomm_lmp_connect_response (self, skb)
  89.  *
  90.  *    
  91.  *
  92.  */
  93. int ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
  94. {
  95. struct sk_buff *skb;
  96. int ret;
  97. IRDA_DEBUG(0, __FUNCTION__"()n");
  98. /* Any userdata supplied? */
  99. if (userdata == NULL) {
  100. skb = dev_alloc_skb(64);
  101. if (!skb)
  102. return -ENOMEM;
  103. /* Reserve space for MUX and LAP header */
  104. skb_reserve(skb, LMP_MAX_HEADER);
  105. } else {
  106. skb = userdata;
  107. /*  
  108.  *  Check that the client has reserved enough space for 
  109.  *  headers
  110.  */
  111. ASSERT(skb_headroom(skb) >= LMP_MAX_HEADER, return -1;);
  112. }
  113. ret = irlmp_connect_response(self->lsap, skb);
  114. return 0;
  115. }
  116. int ircomm_lmp_disconnect_request(struct ircomm_cb *self, 
  117.   struct sk_buff *userdata, 
  118.   struct ircomm_info *info)
  119. {
  120.         struct sk_buff *skb;
  121. int ret;
  122. IRDA_DEBUG(0, __FUNCTION__ "()n");
  123.         if (!userdata) {
  124.                 skb = dev_alloc_skb(64);
  125. if (!skb)
  126. return -ENOMEM;
  127. /*  Reserve space for MUX and LAP header */
  128. skb_reserve(skb, LMP_MAX_HEADER);
  129. userdata = skb;
  130. }
  131. ret = irlmp_disconnect_request(self->lsap, userdata);
  132. return ret;
  133. }
  134. /*
  135.  * Function ircomm_lmp_flow_control (skb)
  136.  *
  137.  *    This function is called when a data frame we have sent to IrLAP has
  138.  *    been deallocated. We do this to make sure we don't flood IrLAP with 
  139.  *    frames, since we are not using the IrTTP flow control mechanism
  140.  */
  141. void ircomm_lmp_flow_control(struct sk_buff *skb)
  142. {
  143. struct irda_skb_cb *cb;
  144. struct ircomm_cb *self;
  145. int line;
  146. ASSERT(skb != NULL, return;);
  147. cb = (struct irda_skb_cb *) skb->cb;
  148. IRDA_DEBUG(2, __FUNCTION__ "()n");
  149.  
  150.         line = cb->line;
  151. self = (struct ircomm_cb *) hashbin_find(ircomm, line, NULL);
  152.         if (!self) {
  153. IRDA_DEBUG(2, __FUNCTION__ "(), didn't find myselfn");
  154.                 return;
  155. }
  156.         ASSERT(self != NULL, return;);
  157. ASSERT(self->magic == IRCOMM_MAGIC, return;);
  158. self->pkt_count--;
  159.         if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
  160.                 IRDA_DEBUG(2, __FUNCTION__ "(), asking TTY to start again!n");
  161.                 self->flow_status = FLOW_START;
  162.                 if (self->notify.flow_indication)
  163.                         self->notify.flow_indication(self->notify.instance, 
  164.      self, FLOW_START);
  165.         }
  166. }
  167.     
  168. /*
  169.  * Function ircomm_lmp_data_request (self, userdata)
  170.  *
  171.  *    Send data frame to peer device
  172.  *
  173.  */
  174. int ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
  175.     int not_used)
  176. {
  177. struct irda_skb_cb *cb;
  178. int ret;
  179. ASSERT(skb != NULL, return -1;);
  180. cb = (struct irda_skb_cb *) skb->cb;
  181.         cb->line = self->line;
  182. IRDA_DEBUG(4, __FUNCTION__"(), sending framen");
  183. skb->destructor = ircomm_lmp_flow_control;
  184.         if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
  185. IRDA_DEBUG(2, __FUNCTION__ "(), asking TTY to slow down!n");
  186.         self->flow_status = FLOW_STOP;
  187.                 if (self->notify.flow_indication)
  188.                       self->notify.flow_indication(self->notify.instance, 
  189.                      self, FLOW_STOP);
  190.         }
  191. ret = irlmp_data_request(self->lsap, skb);
  192. if (ret) {
  193. ERROR(__FUNCTION__ "(), failedn");
  194. dev_kfree_skb(skb);
  195. }
  196. return ret;
  197. }
  198. /*
  199.  * Function ircomm_lmp_data_indication (instance, sap, skb)
  200.  *
  201.  *    Incoming data which we must deliver to the state machine, to check
  202.  *    we are still connected.
  203.  */
  204. int ircomm_lmp_data_indication(void *instance, void *sap,
  205.        struct sk_buff *skb)
  206. {
  207. struct ircomm_cb *self = (struct ircomm_cb *) instance;
  208. IRDA_DEBUG(4, __FUNCTION__"()n");
  209. ASSERT(self != NULL, return -1;);
  210. ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
  211. ASSERT(skb != NULL, return -1;);
  212. ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL);
  213. return 0;
  214. }
  215. /*
  216.  * Function ircomm_lmp_connect_confirm (instance, sap, qos, max_sdu_size, 
  217.  *                                       max_header_size, skb)
  218.  *
  219.  *    Connection has been confirmed by peer device
  220.  *
  221.  */
  222. void ircomm_lmp_connect_confirm(void *instance, void *sap,
  223. struct qos_info *qos, 
  224. __u32 max_seg_size, 
  225. __u8 max_header_size,
  226. struct sk_buff *skb)
  227. {
  228. struct ircomm_cb *self = (struct ircomm_cb *) instance;
  229. struct ircomm_info info;
  230. IRDA_DEBUG(0, __FUNCTION__"()n");
  231. ASSERT(self != NULL, return;);
  232. ASSERT(self->magic == IRCOMM_MAGIC, return;);
  233. ASSERT(skb != NULL, return;);
  234. ASSERT(qos != NULL, return;);
  235. info.max_data_size = max_seg_size;
  236. info.max_header_size = max_header_size;
  237. info.qos = qos;
  238. ircomm_do_event(self, IRCOMM_LMP_CONNECT_CONFIRM, skb, &info);
  239. }
  240. /*
  241.  * Function ircomm_lmp_connect_indication (instance, sap, qos, max_sdu_size,
  242.  *                                         max_header_size, skb)
  243.  *
  244.  *    Peer device wants to make a connection with us
  245.  *
  246.  */
  247. void ircomm_lmp_connect_indication(void *instance, void *sap,
  248.    struct qos_info *qos,
  249.    __u32 max_seg_size,
  250.    __u8 max_header_size,
  251.    struct sk_buff *skb)
  252. {
  253. struct ircomm_cb *self = (struct ircomm_cb *)instance;
  254. struct ircomm_info info;
  255. IRDA_DEBUG(0, __FUNCTION__"()n");
  256. ASSERT(self != NULL, return;);
  257. ASSERT(self->magic == IRCOMM_MAGIC, return;);
  258. ASSERT(skb != NULL, return;);
  259. ASSERT(qos != NULL, return;);
  260. info.max_data_size = max_seg_size;
  261. info.max_header_size = max_header_size;
  262. info.qos = qos;
  263. ircomm_do_event(self, IRCOMM_LMP_CONNECT_INDICATION, skb, &info);
  264. }
  265. /*
  266.  * Function ircomm_lmp_disconnect_indication (instance, sap, reason, skb)
  267.  *
  268.  *    Peer device has closed the connection, or the link went down for some
  269.  *    other reason
  270.  */
  271. void ircomm_lmp_disconnect_indication(void *instance, void *sap, 
  272.       LM_REASON reason,
  273.       struct sk_buff *skb)
  274. {
  275. struct ircomm_cb *self = (struct ircomm_cb *) instance;
  276. struct ircomm_info info;
  277. IRDA_DEBUG(0, __FUNCTION__"()n");
  278. ASSERT(self != NULL, return;);
  279. ASSERT(self->magic == IRCOMM_MAGIC, return;);
  280. info.reason = reason;
  281. ircomm_do_event(self, IRCOMM_LMP_DISCONNECT_INDICATION, skb, &info);
  282. }