Hi...
Boy, it took me a bit of time, but now I've got
patch-2.2.13-irda10 working for me. Dag was right when he mentionned a
work in progress. See patch attached...
Fixed :
o wrong types in irda.h prevent compilation
o typo in wrapper.c & actisys.c
o create SEQPACKET with correct operations
o auto-connect
All is not perfect, though. Using SOCK_DGRAM (unitdata), the
first byte of every received packet is scrapped (missing - I suspect
the receiver path).
And also, connect seems a bit flaky :
-----------------------------
irlap_state_ndm(), media busy!
irlap_state_ndm(), media busy!
irlmp_state_setup_pend() WATCHDOG_TIMEOUT!
irda_get_value_confirm(), IAS query failed!
irda_connect(), connect failed!
irlap_state_ndm(), media busy!
-----------------------------
Have fun...
Jean
diff -u -p linux/include/linux/irda.dag.h linux/include/linux/irda.h
--- linux/include/linux/irda.dag.h Wed Dec 8 07:53:59 1999
+++ linux/include/linux/irda.h Wed Dec 8 08:30:47 1999
@@ -22,6 +22,8 @@
*
********************************************************************/
+#include <linux/types.h> /* for __u8, __u32 & ... */
+
#ifndef KERNEL_IRDA_H
#define KERNEL_IRDA_H
@@ -69,11 +71,11 @@ typedef enum {
} IRDA_DONGLE;
/* Protocol types to be used for SOCK_DGRAM */
-enum {
+typedef enum {
IRDAPROTO_UNITDATA = 0,
IRDAPROTO_ULTRA = 1,
IRDAPROTO_MAX
-};
+} IRDA_DGRAM_PROTOCOLS;
#define SOL_IRLMP 266 /* Same as SOL_IRDA for now */
#define SOL_IRTTP 266 /* Same as SOL_IRDA for now */
@@ -96,21 +98,21 @@ enum {
struct sockaddr_irda {
sa_family_t sir_family; /* AF_IRDA */
- uint8_t sir_lsap_sel; /* LSAP selector */
- uint32_t sir_addr; /* Device address */
+ __u8 sir_lsap_sel; /* LSAP selector */
+ __u32 sir_addr; /* Device address */
char sir_name[25]; /* Usually <service>:IrDA:TinyTP */
};
struct irda_device_info {
- uint32_t saddr; /* Address of local interface */
- uint32_t daddr; /* Address of remote device */
+ __u32 saddr; /* Address of local interface */
+ __u32 daddr; /* Address of remote device */
char info[22]; /* Description */
- uint8_t charset; /* Charset used for description */
- uint8_t hints[2]; /* Hint bits */
+ __u8 charset; /* Charset used for description */
+ __u8 hints[2]; /* Hint bits */
};
struct irda_device_list {
- uint32_t len;
+ __u32 len;
struct irda_device_info dev[1];
};
diff -u -p linux/drivers/net/irda/actisys.dag2.c linux/drivers/net/irda/actisys.c
--- linux/drivers/net/irda/actisys.dag2.c Wed Dec 8 07:15:34 1999
+++ linux/drivers/net/irda/actisys.c Wed Dec 8 07:16:28 1999
@@ -163,7 +163,7 @@ static int actisys_change_speed(struct i
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param; /* Target speed */
- int index = 0;
+ int i = 0;
int ret = 0;
IRDA_DEBUG(4, __FUNCTION__ "(), speed=%d (was %d)\n", speed,
diff -u -p linux/net/irda/wrapper.dag2.c linux/net/irda/wrapper.c
--- linux/net/irda/wrapper.dag2.c Wed Dec 8 07:22:03 1999
+++ linux/net/irda/wrapper.c Wed Dec 8 07:24:52 1999
@@ -220,7 +220,7 @@ static void state_outside_frame(struct d
rx_buff->state = BEGIN_FRAME;
rx_buff->in_frame = TRUE;
- /* Set mbusy when SOP and prev char not SOP (IrLAP 6.13.3)
+ /* Set mbusy when SOP and prev char not SOP (IrLAP 6.13.3) */
irda_device_set_media_busy(dev, TRUE);
break;
case XBOF:
@@ -285,6 +285,8 @@ static void state_link_escape(struct dev
{
switch (byte) {
case BOF: /* New frame? */
+ IRDA_DEBUG(1, __FUNCTION__
+ "(), Discarding incomplete frame\n");
rx_buff->state = BEGIN_FRAME;
irda_device_set_media_busy(dev, TRUE);
break;
@@ -326,6 +328,8 @@ static void state_inside_frame(struct de
switch (byte) {
case BOF: /* New frame? */
+ IRDA_DEBUG(1, __FUNCTION__
+ "(), Discarding incomplete frame\n");
rx_buff->state = BEGIN_FRAME;
irda_device_set_media_busy(dev, TRUE);
break;
diff -u -p linux/net/irda/af_irda.dag4.c linux/net/irda/af_irda.c
--- linux/net/irda/af_irda.dag4.c Wed Dec 8 07:33:10 1999
+++ linux/net/irda/af_irda.c Wed Dec 8 08:50:42 1999
@@ -484,6 +484,77 @@ static int irda_find_lsap_sel(struct ird
}
/*
+ * Function irda_discover_daddr_and_lsap_sel (self, name)
+ *
+ * This try to find a device with the requested service.
+ *
+ * It basically look into the discovery log. For each address in the list,
+ * it queries the LM-IAS of the device to find if this device offer
+ * the requested service.
+ * At the first node that support the service requested, the function
+ * set both the destination address and the lsap selector to point
+ * on the service on that device.
+ */
+static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+{
+ discovery_t *discovery;
+ int err = -ENETUNREACH;
+
+ IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name);
+
+ ASSERT(self != NULL, return -1;);
+
+ /* Tell IrLMP we want to be notified */
+ irlmp_update_client(self->ckey, self->mask, NULL,
+ irda_discovery_indication);
+
+ /* Do some discovery */
+ irlmp_discovery_request(self->nslots);
+
+ /* Check if the we got some results */
+ if (!cachelog)
+ /* Wait for answer */
+ /*interruptible_sleep_on(&self->discovery_wait);*/
+ return -EAGAIN;
+
+ /*
+ * Now, check all discovered devices (if any), and connect
+ * client only about the services that the client is
+ * interested in
+ */
+ discovery = (discovery_t *) hashbin_get_first(cachelog);
+ while (discovery != NULL) {
+ /* Mask out the ones we don't want */
+ if (discovery->hints.word & self->mask) {
+ /* Try this address */
+ self->daddr = discovery->daddr;
+ IRDA_DEBUG(1, __FUNCTION__ "(), trying daddr = %08x\n",
+self->daddr);
+
+ /* Query remote LM-IAS for this service */
+ err = irda_find_lsap_sel(self, name);
+ if (err == 0)
+ /* We found the requested service */
+ break;
+ }
+
+ /* Next node, maybe we will be more lucky... */
+ discovery = (discovery_t *) hashbin_get_next(cachelog);
+ }
+ cachelog = NULL;
+
+ /* Check out what we found */
+ if(err) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), cannot discover requested service
+''%s'' in any discovered device !!!\n", name);
+ self->daddr = 0; /* Guessing */
+ return(err);
+ }
+
+ IRDA_DEBUG(0, __FUNCTION__ "(), discovered requested service ''%s'' at address
+%08x\n", name, self->daddr);
+
+ return 0;
+}
+
+/*
* Function irda_getname (sock, uaddr, uaddr_len, peer)
*
* Return the our own, or peers socket address (sockaddr_irda)
@@ -735,17 +806,25 @@ static int irda_connect(struct socket *s
return -EINVAL;
/* Check if user supplied the required destination device address */
- if (!addr->sir_addr)
- return -EINVAL;
-
- self->daddr = addr->sir_addr;
- IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
-
- /* Query remote LM-IAS */
- err = irda_find_lsap_sel(self, addr->sir_name);
- if (err) {
- IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
- return err;
+ if (!addr->sir_addr) {
+ /* Try to find one suitable */
+ err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
+ if (err) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), auto-connect failed!\n");
+ return -EINVAL;
+ }
+ }
+ else {
+ /* Use the one provided by the user */
+ self->daddr = addr->sir_addr;
+ IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
+
+ /* Query remote LM-IAS */
+ err = irda_find_lsap_sel(self, addr->sir_name);
+ if (err) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+ return err;
+ }
}
/* Check if we have opened a local TSAP */
@@ -838,6 +917,7 @@ static int irda_create(struct socket *so
case SOCK_SEQPACKET:
sock->ops = &irda_seqpacket_ops;
self->max_sdu_size_rx = TTP_SAR_UNBOUND;
+ break;
case SOCK_DGRAM:
switch (protocol) {
case IRDAPROTO_ULTRA:
@@ -1043,6 +1123,9 @@ static int irda_recvmsg_dgram(struct soc
copied = skb->len;
if (copied > size) {
+ IRDA_DEBUG(2, __FUNCTION__
+ "(), Received truncated frame (%d < %d)!\n",
+ copied, size);
copied = size;
msg->msg_flags |= MSG_TRUNC;
}