00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <linux/sched.h>
00033 #include <linux/init.h>
00034
00035 #include <net/irda/irda.h>
00036 #include <net/irda/irlmp.h>
00037 #include <net/irda/iriap.h>
00038
00039 #include <net/irda/ircomm_event.h>
00040 #include <net/irda/ircomm_lmp.h>
00041
00042
00043
00044
00045
00046
00047
00048 int ircomm_open_lsap(struct ircomm_cb *self)
00049 {
00050 notify_t notify;
00051
00052 IRDA_DEBUG(0, __FUNCTION__ "()\n");
00053
00054
00055 irda_notify_init(¬ify);
00056 notify.data_indication = ircomm_lmp_data_indication;
00057 notify.connect_confirm = ircomm_lmp_connect_confirm;
00058 notify.connect_indication = ircomm_lmp_connect_indication;
00059 notify.disconnect_indication = ircomm_lmp_disconnect_indication;
00060 notify.instance = self;
00061 strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
00062
00063 self->lsap = irlmp_open_lsap(LSAP_ANY, ¬ify, 0);
00064 if (!self->lsap) {
00065 IRDA_DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
00066 return -1;
00067 }
00068 self->slsap_sel = self->lsap->slsap_sel;
00069
00070
00071
00072
00073 self->issue.data_request = ircomm_lmp_data_request;
00074 self->issue.connect_request = ircomm_lmp_connect_request;
00075 self->issue.connect_response = ircomm_lmp_connect_response;
00076 self->issue.disconnect_request = ircomm_lmp_disconnect_request;
00077
00078 return 0;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 int ircomm_lmp_connect_request(struct ircomm_cb *self,
00088 struct sk_buff *userdata,
00089 struct ircomm_info *info)
00090 {
00091 int ret = 0;
00092
00093 IRDA_DEBUG(0, __FUNCTION__ "()\n");
00094
00095 ret = irlmp_connect_request(self->lsap, info->dlsap_sel,
00096 info->saddr, info->daddr, NULL, userdata);
00097 return ret;
00098 }
00099
00100
00101
00102
00103
00104
00105
00106 int ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *skb)
00107 {
00108 int ret;
00109
00110 IRDA_DEBUG(0, __FUNCTION__"()\n");
00111
00112 ret = irlmp_connect_response(self->lsap, skb);
00113
00114 return 0;
00115 }
00116
00117 int ircomm_lmp_disconnect_request(struct ircomm_cb *self,
00118 struct sk_buff *userdata,
00119 struct ircomm_info *info)
00120 {
00121 struct sk_buff *skb;
00122 int ret;
00123
00124 IRDA_DEBUG(0, __FUNCTION__ "()\n");
00125
00126 if (!userdata) {
00127 skb = dev_alloc_skb(64);
00128 if (!skb)
00129 return -ENOMEM;
00130
00131
00132 skb_reserve(skb, LMP_MAX_HEADER);
00133 userdata = skb;
00134 }
00135 ret = irlmp_disconnect_request(self->lsap, userdata);
00136
00137 return ret;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147 void ircomm_lmp_flow_control(struct sk_buff *skb)
00148 {
00149 struct irda_skb_cb *cb;
00150 struct ircomm_cb *self;
00151 int line;
00152
00153 ASSERT(skb != NULL, return;);
00154
00155 cb = (struct irda_skb_cb *) skb->cb;
00156
00157 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00158
00159 line = cb->line;
00160
00161 self = (struct ircomm_cb *) hashbin_find(ircomm, line, NULL);
00162 if (!self) {
00163 IRDA_DEBUG(2, __FUNCTION__ "(), didn't find myself\n");
00164 return;
00165 }
00166
00167 ASSERT(self != NULL, return;);
00168 ASSERT(self->magic == IRCOMM_MAGIC, return;);
00169
00170 self->pkt_count--;
00171
00172 if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
00173 IRDA_DEBUG(2, __FUNCTION__ "(), asking TTY to start again!\n");
00174 self->flow_status = FLOW_START;
00175 if (self->notify.flow_indication)
00176 self->notify.flow_indication(self->notify.instance,
00177 self, FLOW_START);
00178 }
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 int ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb,
00188 int not_used)
00189 {
00190 struct irda_skb_cb *cb;
00191 int ret;
00192
00193 ASSERT(skb != NULL, return -1;);
00194
00195 cb = (struct irda_skb_cb *) skb->cb;
00196
00197 cb->line = self->line;
00198
00199 IRDA_DEBUG(4, __FUNCTION__"(), sending frame\n");
00200
00201 skb->destructor = ircomm_lmp_flow_control;
00202
00203 if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
00204 IRDA_DEBUG(2, __FUNCTION__ "(), asking TTY to slow down!\n");
00205 self->flow_status = FLOW_STOP;
00206 if (self->notify.flow_indication)
00207 self->notify.flow_indication(self->notify.instance,
00208 self, FLOW_STOP);
00209 }
00210 ret = irlmp_data_request(self->lsap, skb);
00211 if (ret) {
00212 ERROR(__FUNCTION__ "(), failed\n");
00213 dev_kfree_skb(skb);
00214 }
00215
00216 return ret;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 int ircomm_lmp_data_indication(void *instance, void *sap,
00226 struct sk_buff *skb)
00227 {
00228 struct ircomm_cb *self = (struct ircomm_cb *) instance;
00229
00230 IRDA_DEBUG(4, __FUNCTION__"()\n");
00231
00232 ASSERT(self != NULL, return -1;);
00233 ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
00234 ASSERT(skb != NULL, return -1;);
00235
00236 ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL);
00237
00238 return 0;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 void ircomm_lmp_connect_confirm(void *instance, void *sap,
00249 struct qos_info *qos,
00250 __u32 max_seg_size,
00251 __u8 max_header_size,
00252 struct sk_buff *skb)
00253 {
00254 struct ircomm_cb *self = (struct ircomm_cb *) instance;
00255 struct ircomm_info info;
00256
00257 IRDA_DEBUG(0, __FUNCTION__"()\n");
00258
00259 ASSERT(self != NULL, return;);
00260 ASSERT(self->magic == IRCOMM_MAGIC, return;);
00261 ASSERT(skb != NULL, return;);
00262 ASSERT(qos != NULL, return;);
00263
00264 info.max_data_size = max_seg_size;
00265 info.max_header_size = max_header_size;
00266 info.qos = qos;
00267
00268 ircomm_do_event(self, IRCOMM_LMP_CONNECT_CONFIRM, skb, &info);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278 void ircomm_lmp_connect_indication(void *instance, void *sap,
00279 struct qos_info *qos,
00280 __u32 max_seg_size,
00281 __u8 max_header_size,
00282 struct sk_buff *skb)
00283 {
00284 struct ircomm_cb *self = (struct ircomm_cb *)instance;
00285 struct ircomm_info info;
00286
00287 IRDA_DEBUG(0, __FUNCTION__"()\n");
00288
00289 ASSERT(self != NULL, return;);
00290 ASSERT(self->magic == IRCOMM_MAGIC, return;);
00291 ASSERT(skb != NULL, return;);
00292 ASSERT(qos != NULL, return;);
00293
00294 info.max_data_size = max_seg_size;
00295 info.max_header_size = max_header_size;
00296 info.qos = qos;
00297
00298 ircomm_do_event(self, IRCOMM_LMP_CONNECT_INDICATION, skb, &info);
00299 }
00300
00301
00302
00303
00304
00305
00306
00307 void ircomm_lmp_disconnect_indication(void *instance, void *sap,
00308 LM_REASON reason,
00309 struct sk_buff *skb)
00310 {
00311 struct ircomm_cb *self = (struct ircomm_cb *) instance;
00312 struct ircomm_info info;
00313
00314 IRDA_DEBUG(0, __FUNCTION__"()\n");
00315
00316 ASSERT(self != NULL, return;);
00317 ASSERT(self->magic == IRCOMM_MAGIC, return;);
00318
00319 info.reason = reason;
00320
00321 ircomm_do_event(self, IRCOMM_LMP_DISCONNECT_INDICATION, skb, &info);
00322 }