Greg KH wrote:
> On Mon, Jul 03, 2006 at 10:24:26PM -0300, Manuel Naranjo wrote:
>> Greg KH wrote:
>>> On Mon, Jul 03, 2006 at 07:32:55PM -0300, Manuel Naranjo wrote:
>>>> Hi:
>>>> I'm working on AIRcable USB driver, I was about to send a patch diff 
>>>> file as Greg KH recommended me, when I found a bug, which will not make 
>>>> the system crash, but is a bug at least.
>>>> The problem that I'm having is the amount of data this devices can 
>>>> receive is limited to 180 bytes, any amount of data over 180 bytes is 
>>>> drop off. What I had tried was dividing the hole data in 180 bytes 
>>>> packages starting a "for" and making a usb_fill_bulk_urb with it 
>>>> respective usb_submit_urb on every step of the loop, but here is where 
>>>> my problems starts. If data arrives when ever I'm inside of the loop a 
>>>> Read Bulk In is launched an makes my driver crash, I know this is a 
>>>> problem in my code, but here is where my question comes, how can I add 
>>>> the write function with the remaining packages to the Kernel stack, so 
>>>> when data arrives I'm not writting to the port, and I'm able to read 
>>> >from it.
>>>> If there is the need to send source code, I have no problem, I do not 
>>>> because it what i should send is about 100 lines and do not want to 
>>>> bother anyone.
>>> Send the patch, it will be easier to show what you mean that way.
>>>
>>> thanks,
>>>
>>> greg k-h
>>>

Here is the patch I generetaded using a kernel 2.6.16.18 (The one 
included on the CD of drivers development). This is a working version, 
that can handle transfers at to 180 bytes, the one i was asking is a 
slight different. On the aircable_write there is a for next, and what i 
did was sending the URB on every interaction. I can generate a diff 
patch to show mi idea, but I'm sending this version because I know it 
works quite well.

Thanks,
Manuel

diff -uprN -X Documentation/dontdiff 
a/drivers/usb/serial/AIRcable-USB-serial.c 
b/drivers/usb/serial/AIRcable-USB-serial.c
--- a/drivers/usb/serial/AIRcable-USB-serial.c  1969-12-31 
21:00:00.000000000 -0300
+++ b/drivers/usb/serial/AIRcable-USB-serial.c  2006-07-04 
09:34:10.000000000 -0300
@@ -0,0 +1,309 @@
+/*
+ * AIRcable USB Bluetooth dondgle Driver.
+ *
+ * This driver is a modified version of USB Serial Converter driver,
+ * that lets AIRcable devices work.
+ *
+ * The AIRcable USB Bluetooth Dongles has two interfaces, the first
+ * one is usless for serial working, I think it must be for firmware
+ * updating.
+ * The second interfaces has a bulk in and a bulk out, and is the one
+ * used for serial transactions.
+ * AIRcable USB Bluetooth Dongles uses a modified version of the standar
+ * USB serial generic protocol, it sends data in packages of 124 bytes,
+ * and adds at the begging of each package 4 bytes for header. See
+ * AIRcable-USB-serial.h for Header Information.
+ *
+ * I have also taken some info from a Greg Kroah-Hartman article
+ *     url: http://www.linuxjournal.com/article/6573
+ *
+ * Copyright (C) 2006
+ *         Manuel Francisco Naranjo ([EMAIL PROTECTED])
+ *
+ * License: GNU/GPL v2 or newer.
+ *
+ * (03/07/2006) manuelnaranjo
+ *     Trying to fix a bug, if more than 1 dongle is connected to the
+ *     computer and there are transfers of more than 180 bytes (without
+ *     including the Header) the driver crashes.
+ *
+ * (23/06/2006) manuelnaranjo
+ *     v0.1 Started
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <../drivers/usb/serial/usb-serial.h>
+#include "AIRcable-USB-serial.h"
+
+
+static int debug;
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0b2"
+#define DRIVER_AUTHOR "Naranjo, Manuel Francisco. email: 
[EMAIL PROTECTED]"
+#define DRIVER_DESC "AIRcable USB Driver"
+
+
+/* ID table that will be registered with USB core */
+static struct usb_device_id id_table [] = {
+        { USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) },
+        { },
+};
+MODULE_DEVICE_TABLE (usb, id_table);
+
+
+
+/* Methods declaration */
+int aircable_probe (struct usb_serial *serial, const struct 
usb_device_id *id);
+int aircable_write(struct usb_serial_port *port, const unsigned char 
*buf, int count);
+void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs);
+
+/* All device info needed for AIRcable USB device */
+static struct usb_serial_device_type aircable_device = {
+    .owner =                   THIS_MODULE,
+    .name =                    "AIRcable USB serial (device)",
+    .short_name =              "aircable_device",
+    .id_table =                id_table,
+    .num_ports =               1,
+    .probe=                    aircable_probe,
+    .write=                    aircable_write,
+    .read_bulk_callback=       aircable_read_bulk_callback,
+};
+
+static struct usb_driver aircable_driver = {
+       .name =         "AIRcable USB serial (driver)",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,
+       .id_table =     id_table,
+};
+
+/* Methods implementation */
+
+/* Based on serial_probe */
+int aircable_probe (struct usb_serial *serial, const struct 
usb_device_id *id)
+{
+       struct usb_host_interface *iface_desc = 
serial->interface->cur_altsetting;
+       struct usb_endpoint_descriptor *endpoint;
+       int num_bulk_out=0;
+
+       int i;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+       
+               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+                   ((endpoint->bmAttributes & 3) == 0x02)) {
+                       dbg("found bulk out on endpoint %d", i);                
        
+                       ++num_bulk_out;
+               }
+       }
+
+       if (num_bulk_out == 0) {
+               dbg("Invalid interface, discarding.\n");
+               return -5;
+       }
+       return 0;
+}
+
+
+
+/*
+ * Based on Generic_write and AIRcable Windows driver
+ * Thanks Juergen Kienhoefer from AIRcable for the support, and
+ * giving me access to their Windows Driver.
+ */
+int aircable_write(struct usb_serial_port *port, const unsigned char 
*pSrcBuf, int count)
+{
+       struct usb_serial *serial = port->serial;
+       unsigned char *pBuf;    
+       int result;
+       unsigned long no_headers;
+       unsigned long payload_length;
+       unsigned long length;
+       unsigned long i;
+       unsigned long offset;   
+       unsigned long src_offset;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (count == 0) {
+               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               return (0);
+       }
+
+       /* only do something if we have a bulk out endpoint */
+       if (serial->num_bulk_out) {
+               if (port->write_urb->status == -EINPROGRESS) {
+                       dbg("%s - already writing", __FUNCTION__);
+                       return (0);
+               }
+               
+               dbg("Writting: %s", pSrcBuf);
+
+               no_headers = (count / MAX_HCI_FRAMESIZE) + 1;
+
+               pBuf = kmalloc(count + (no_headers *HCI_HEADER_LENGTH 
),GFP_KERNEL);
+               memset (pBuf, 0, count + (no_headers *HCI_HEADER_LENGTH ));
+
+               payload_length = count;
+               length = 0;
+
+               for(i = 0; i < no_headers; i++) {
+                       if(payload_length >= MAX_HCI_FRAMESIZE)
+                               length = MAX_HCI_FRAMESIZE;
+                       else
+                               length = payload_length;
+                       payload_length -= length;
+
+                       offset = i * (MAX_HCI_FRAMESIZE + HCI_HEADER_LENGTH);
+                       src_offset = i * MAX_HCI_FRAMESIZE;
+                       pBuf[offset] = HCI_HEADER_0;
+                       pBuf[offset+1] = HCI_HEADER_1;
+                       pBuf[offset+2] = (unsigned char) length;
+                       pBuf[offset+3] = (unsigned char)(length >> 8);
+
+                       memcpy(pBuf + offset + HCI_HEADER_LENGTH, pSrcBuf + 
src_offset, length);
+               }
+
+               port->write_urb->transfer_buffer = pBuf;
+               
+               /* set up our urb */
+               usb_fill_bulk_urb (port->write_urb, serial->dev,
+                                  usb_sndbulkpipe (serial->dev, 
port->bulk_out_endpointAddress),
+                                  port->write_urb->transfer_buffer, (count + 
(no_headers 
*HCI_HEADER_LENGTH )),
+                                  serial->type->write_bulk_callback, port);
+
+               /* send the data out the bulk port */
+               result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+
+               if (result)
+                       dev_err(&port->dev, "%s - failed submitting write urb, 
error %d\n", 
__FUNCTION__, result);
+               else
+                       result = count;
+
+               return result;
+
+               kfree(pBuf);
+       }
+
+       /* no bulk out, so return 0 bytes written */
+       return (0);
+}
+
+/*
+ * This internal function simply drops the Header on every read,
+ * It must only recive complete packages.
+ */
+void aircable_parse_read(struct tty_struct *tty, unsigned char *data, 
int lenght)
+{
+       int i;          
+       if ( lenght > HCI_HEADER_LENGTH) {
+               for (i = HCI_HEADER_LENGTH; i < lenght; i++) {
+                       /* if we insert more than TTY_FLIPBUF_SIZE characters, 
we drop them. */
+                       if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+                               tty_flip_buffer_push(tty);
+                       }
+                       
+                       /* this doesn't actually push the data through unless 
tty->low_latency is set */
+                       tty_insert_flip_char(tty, data[i], 0);
+               }       
+       }
+}
+
+void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial *serial = port->serial;
+       struct tty_struct *tty;
+       unsigned char *data;
+       unsigned long no_packages;
+       unsigned long remaining, package_length;        
+       unsigned long i;
+       int result;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (urb->status) {
+               dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, 
urb->status);
+               return;
+       }
+       
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, 
urb->actual_length, urb->transfer_buffer);
+
+       tty = port->tty;        
+       if (tty && urb->actual_length) {                
+               //Does this package includes more information than the header???
+               if (urb->actual_length > HCI_HEADER_LENGTH) {
+                       remaining = urb->actual_length;
+
+                       no_packages = (urb->actual_length / 
(HCI_HEADER_LENGTH+MAX_HCI_FRAMESIZE))+1;
+                       
+                       for (i = 0; i < no_packages ; ++i) {
+                               if (remaining > 
(HCI_HEADER_LENGTH+MAX_HCI_FRAMESIZE))                          
+                                       package_length = 
HCI_HEADER_LENGTH+MAX_HCI_FRAMESIZE;
+                               else
+                                       package_length = remaining;             
                
+
+                               remaining -= package_length;                    
        
+
+                               data = kmalloc(package_length,GFP_KERNEL);
+
+                               memset (data, 0, package_length);
+                               memcpy(data, urb->transfer_buffer + 
(HCI_HEADER_LENGTH+MAX_HCI_FRAMESIZE) * (i), package_length);
+                               aircable_parse_read(tty, data, package_length);
+                               
+                               kfree(data);
+                       }
+                       tty_flip_buffer_push(tty);
+               }
+       }
+       
+       /* Continue trying to always read  */
+       usb_fill_bulk_urb (port->read_urb, serial->dev,
+                       usb_rcvbulkpipe (serial->dev,
+                                       port->bulk_in_endpointAddress),
+                       port->read_urb->transfer_buffer,
+                       port->read_urb->transfer_buffer_length,
+                       serial->type->read_bulk_callback, port);
+       result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+       if (result)
+               dev_err(&port->dev, "%s - failed resubmitting read urb, error 
%d\n", 
__FUNCTION__, result);
+}
+
+/* END OF Methods Implementatio */
+
+static int __init aircable_init (void)
+{
+       usb_serial_register (&aircable_device); 
+       usb_register (&aircable_driver);
+       return 0;
+}
+
+static void __exit aircable_exit (void)
+{
+       usb_deregister (&aircable_driver);
+       usb_serial_deregister (&aircable_device);       
+}
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_VERSION( DRIVER_VERSION );
+MODULE_LICENSE("GPL");
+
+
+module_init(aircable_init);
+module_exit(aircable_exit);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff -uprN -X Documentation/dontdiff 
a/drivers/usb/serial/AIRcable-USB-serial.h 
b/drivers/usb/serial/AIRcable-USB-serial.h
--- a/drivers/usb/serial/AIRcable-USB-serial.h  1969-12-31 
21:00:00.000000000 -0300
+++ b/drivers/usb/serial/AIRcable-USB-serial.h  2006-07-04 
09:34:53.000000000 -0300
@@ -0,0 +1,33 @@
+/* AIRcable USB Bluetooth dondgle Driver.
+ *
+ * This driver is a modified version of USB Serial Converter driver,
+ * that lets AIRcable devices work.
+ *
+ * Copyright (C) 2006
+ *         Manuel Francisco Naranjo ([EMAIL PROTECTED])
+ *
+ * License: GNU/GPL v2 or newer.
+ *
+ */
+
+
+#ifndef __AIRCABLE_USB_LINUX_H
+#define __AIRCABLE_USB_LINUX_H
+
+#define AIRCABLE_VID           0x16CA  /* Vendor Id */
+#define AIRCABLE_USB_PID       0x1502  /* Product Id */
+
+/* The following defintions are required to Add/Strip HCI headers from 
URB sent over
+   bulk endpoints to Bluecore2-External */
+#define HCI_HEADER_LENGTH      (0x4)
+#define HCI_HEADER_0           (0x20)
+#define HCI_HEADER_1           (0x29)
+#define MAX_HCI_FRAMESIZE      (60) //124 252 956
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) if (debug) do { printk(KERN_DEBUG "%s: " 
format "\n" , __FILE__ , ## arg); } while (0)
+#endif 
+/* ifdef __LINUX_USB_SERIAL_H */
+
+
diff -uprN -X Documentation/dontdiff a/drivers/usb/serial/Kconfig 
b/drivers/usb/serial/Kconfig
--- a/drivers/usb/serial/Kconfig        2006-03-20 02:53:29.000000000 -0300
+++ b/drivers/usb/serial/Kconfig        2006-07-04 09:37:38.000000000 -0300
@@ -484,6 +484,15 @@ config USB_SERIAL_OMNINET
          To compile this driver as a module, choose M here: the
          module will be called omninet.

+config USB_SERIAL_AIRCABLE
+       tristate "AIRcable USB Bluetooth dongle Driver (EXPERIMENTAL)"
+       depends on USB_SERIAL && EXPERIMENTAL
+       help
+         Say Y here if you want to use an AIRcable USB Bluetooth dongle.
+
+         To compile this driver as a module, choose M here: the
+         module will be called AIRcable-USB-serial.
+
  config USB_EZUSB
        bool
        depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || 
USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
diff -uprN -X Documentation/dontdiff a/drivers/usb/serial/Makefile 
b/drivers/usb/serial/Makefile
--- a/drivers/usb/serial/Makefile       2006-03-20 02:53:29.000000000 -0300
+++ b/drivers/usb/serial/Makefile       2006-07-04 09:38:29.000000000 -0300
@@ -40,4 +40,5 @@ obj-$(CONFIG_USB_SERIAL_TI)                   += ti_usb_
  obj-$(CONFIG_USB_SERIAL_VISOR)                        += visor.o
  obj-$(CONFIG_USB_SERIAL_WHITEHEAT)            += whiteheat.o
  obj-$(CONFIG_USB_SERIAL_XIRCOM)                       += keyspan_pda.o
+obj-$(CONFIG_USB_SERIAL_AIRCABLE)              += AIRcable-USB-serial.o


Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to