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