Hi Manuel, On Sat, 8 Jul 2006 15:27:22 -0300 "Naranjo Manuel Francisco" <[EMAIL PROTECTED]> wrote:
| 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> Why don't '#include "usbserial.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) We do have a debug macro in usbserial.h already. | + | +/* | + * 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; Are you sure 'length' and 'result' must be zeroed here? | + 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); | + Blank line. | + if (result){ | + dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", | + __FUNCTION__, result); | + kfree(buffer); | + count = result; | + } | + | + usb_free_urb (urb); Remove that space please, that's also happens in other places also.. | + 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; Why? | + | + 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 -- Luiz Fernando N. Capitulino ------------------------------------------------------------------------- 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