Hi:
I made the changes suggested by Greg and Oliver. I have some strong
changes to my driver. I have been reading the FTDI driver and taken
some ideas from there.

I think that the bug is corrected, I have been able to transfer 300
bytes without problem. Even more I have reached the hardware limit,
sending 300 bytes over heats one of it components, and the device
stops transmitting. I do not think that is a problem of my driver :),
I hope.

I think that all correcting suggested have been taken into account,
please take a look at it, and give me your opinion. If you think that
the older one was better please let me know.

One thing I have not been able to remove is the probe function, I have
tried with different options, they are commented in my source. The
reason why I do not remove this function is that with out it the
driver attaches himself to both interfaces, which is something really
annoying.


Signed-off-by: Naranjo, Manuel Francisco <[EMAIL PROTECTED]>

diff -uprN -X linux-vanilla/Documentation/dontdiff
linux-vanilla/drivers/usb/serial/aircable.c
linux/drivers/usb/serial/aircable.c
--- linux-vanilla/drivers/usb/serial/aircable.c 1969-12-31
21:00:00.000000000 -0300
+++ linux/drivers/usb/serial/aircable.c 2006-07-08 15:08:36.000000000 -0300
@@ -0,0 +1,314 @@
+/*
+ * AIRcable USB Bluetooth dondgle Driver.
+ *
+ * Copyright (C) 2006 Manuel Francisco Naranjo ([EMAIL PROTECTED])
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This driver uses the USB Serial Core driver, to make AIRcable USB
+ * dongles 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 works like an standard ACM but witj little
+ * changes, it sends data in packages of 124 bytes, and adds at the begging
+ * of each package 4 bytes for header.
+ *
+ * I have also taken some info from a Greg Kroah-Hartman article
+ * url: http://www.linuxjournal.com/article/6573
+ * And from Linux Device Driver Kit CD, which is a great work, the authors
+ * taken the work to recopile lots of information an knowladge in drivers
+ * development and made it all avaible inside a cd.
+ * URL: http://kernel.org/pub/linux/kernel/people/gregkh/ddk/
+ *
+ */
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#include <linux/usb.h>
+
+#include <../drivers/usb/serial/usb-serial.h>
+
+
+static int debug;
+
+#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 */
+#define HCI_HEADER_LENGTH      (0x4)
+#define HCI_HEADER_0           (0x20)
+#define HCI_HEADER_1           (0x29)
+#define MAX_HCI_FRAMESIZE      (60) //124 252 956
+#define HCI_COMPLETE_FRAME     64
+
+/* Debug macro */
+#undef dbg
+#define dbg(format, arg...) if (debug) do { printk(KERN_DEBUG "%s: "
format "\n", __FILE__ , ## arg); } while (0)
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0b2"
+#define DRIVER_AUTHOR "Naranjo, Manuel Francisco <[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 */
+static int aircable_probe (struct usb_serial *serial, const
+                                               struct usb_device_id *id);
+static int aircable_write(struct usb_serial_port *port,
+                                       const unsigned char *buf, int count);
+static void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs);
+static void aircable_write_bulk_callback(struct urb *urb, struct
pt_regs *regs);
+
+/* All device info needed for AIRcable USB device */
+static struct usb_serial_driver aircable_device = {
+       .description =                  "AIRcableUSB",
+       .id_table =                     id_table,
+       .num_ports =                    1,
+       .probe=                                 aircable_probe,
+       .write=                                 aircable_write,
+//     .num_interrupt_in=              0,
+//     .num_interrupt_out=             0,
+//     .num_bulk_in=                   82,
+//     .num_bulk_out=                  02,
+       .write_bulk_callback=   aircable_write_bulk_callback,
+       .read_bulk_callback=    aircable_read_bulk_callback,
+};
+
+static struct usb_driver aircable_driver = {
+       .name =         "AIRcableUSB",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,  
+       .id_table =     id_table,
+};
+
+/* Methods implementation */
+
+/* Based on serial_probe */
+static int aircable_probe (struct usb_serial *serial, const
+                                               struct usb_device_id *id)
+{
+       //This was taken from usb-serial.c probe
+       //And addapted to fit AIRcable needs
+       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)) {
+                       /* we found a bulk out endpoint */
+                       dbg("found bulk out on endpoint %d", i);        
+       
+                       ++num_bulk_out;
+               }
+       }
+       if (num_bulk_out == 0) {
+               dbg("Invalid interface, discarding.\n");
+               return ENODEV;
+       }
+       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.
+ */
+static int aircable_write(struct usb_serial_port *port,
+                                                                               
const unsigned char *source, int count)
+{
+       struct usb_serial *serial = port->serial;
+       struct urb *urb;
+       unsigned char *buffer;
+       int result;
+       int no_headers;
+       int payload_length;
+       int length;
+       int i;
+       int offset;
+       int src_offset;
+       
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (count == 0){
+               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               return 0;
+       }
+
+       no_headers = (count / MAX_HCI_FRAMESIZE) + 1;
+       payload_length = count;
+       length = 0;
+       result=0;
+       buffer = kzalloc(count + no_headers * HCI_HEADER_LENGTH ,GFP_ATOMIC);
+       if (!buffer){
+               err("%s ran out of kernel memory for urb ...", __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               err("%s - no more free urbs", __FUNCTION__);
+               kfree (buffer);
+               return -ENOMEM;
+       }
+
+       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 * HCI_COMPLETE_FRAME;
+               src_offset = i * MAX_HCI_FRAMESIZE;
+               buffer[offset] = HCI_HEADER_0;
+               buffer[offset+1] = HCI_HEADER_1;
+               buffer[offset+2] = (unsigned char) length;
+               buffer[offset+3] = (unsigned char)(length >> 8);
+               memcpy(buffer + offset + HCI_HEADER_LENGTH, source + 
src_offset,length);
+       }
+               
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, length +
+                                                                               
                        HCI_HEADER_LENGTH , buffer);
+       usb_fill_bulk_urb (urb, serial->dev,
+               usb_sndbulkpipe (serial->dev, port->bulk_out_endpointAddress),
+               buffer, count + no_headers * HCI_HEADER_LENGTH ,
+               aircable_write_bulk_callback, port);
+
+       result = usb_submit_urb(urb, GFP_ATOMIC);
+
+       if (result){
+               dev_err(&port->dev, "%s - failed submitting write urb, error 
%d\n",
+                                                                               
                                __FUNCTION__, result);
+               kfree(buffer);
+               count = result;
+       }
+
+       usb_free_urb (urb);
+       dbg("%s write returning: %d", __FUNCTION__, count);
+
+       return count;
+}
+
+static void aircable_write_bulk_callback (struct urb *urb, struct
pt_regs *regs)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+
+       /* free up the transfer buffer, as usb_free_urb() does not do this */
+       kfree (urb->transfer_buffer);
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       port->write_urb_busy = 0;
+       
+       if (urb->status) {
+               dbg("nonzero write bulk status received: %d", urb->status);
+               return;
+       }
+       usb_serial_port_softint((void *)port);
+       schedule_work(&port->work);
+}
+
+static 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;
+       }
+       
+       tty = port->tty;        
+       if (tty && urb->actual_length) {
+               usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                                                                       
urb->actual_length , urb->transfer_buffer);
+               if (urb->actual_length > HCI_HEADER_LENGTH){
+                       remaining = urb->actual_length;
+                       no_packages = urb->actual_length / (HCI_COMPLETE_FRAME);
+                       if (urb->actual_length % HCI_COMPLETE_FRAME != 0)
+                               no_packages+=1;
+                       for (i = 0; i < no_packages ; ++i) {
+                               if (remaining > (HCI_COMPLETE_FRAME))
+                                       package_length = HCI_COMPLETE_FRAME;
+                               else
+                                       package_length = remaining;
+                               remaining -= package_length;
+                               data = kmalloc(package_length - 
HCI_HEADER_LENGTH, GFP_ATOMIC);
+                               memcpy(data, urb->transfer_buffer + 
HCI_HEADER_LENGTH +
+                                       (HCI_COMPLETE_FRAME)*(i),
+                                       package_length - HCI_HEADER_LENGTH);
+                               tty_buffer_request_room(tty,package_length - 
HCI_HEADER_LENGTH);
+                               tty_insert_flip_string(tty,data,
+                                                                               
        package_length - HCI_HEADER_LENGTH);
+                               tty_flip_buffer_push(tty);
+                               kfree(data);    
+                       }
+               }
+       }
+       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 linux-vanilla/Documentation/dontdiff
linux-vanilla/drivers/usb/serial/Kconfig
linux/drivers/usb/serial/Kconfig
--- linux-vanilla/drivers/usb/serial/Kconfig    2006-03-20 02:53:29.000000000 
-0300
+++ linux/drivers/usb/serial/Kconfig    2006-07-08 15:09:44.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.
+
 config USB_EZUSB
        bool
        depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM ||
USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
diff -uprN -X linux-vanilla/Documentation/dontdiff
linux-vanilla/drivers/usb/serial/Makefile
linux/drivers/usb/serial/Makefile
--- linux-vanilla/drivers/usb/serial/Makefile   2006-03-20
02:53:29.000000000 -0300
+++ linux/drivers/usb/serial/Makefile   2006-07-08 15:09:54.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.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