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