From: Samuel O. <sa...@so...> - 2006-05-24 11:05:58
|
Hi Nick, Nick Fedchik wrote : > Hello irda-users! > > Here the updated patch for 2.6.16 kernel > > Know bug: When non appliacable firmware loaded first, we have a same > buffer > for applicable firmware (next loaded) as for the first-loaded firmware > > kernel: stir421x_patching(): Received firmware 42101001.sb (8299 bytes) > kernel: stir421x_patching(): Firmware ver 4097 <> bcdDevice 4098 > kernel: stir421x_patching(): Received firmware 42101002.sb (8299 bytes) > kernel: stir421x_patching(): Firmware ver 4097 <> bcdDevice 4098 > kernel: stir421x_patching(): No valid firmware found, return -22 > kernel: STIR421X: No firmware found for device irda0 > kernel: IrDA: Unregistering device irda0 > > Now I don't know how to fix it, guess it mostly related to the "firmware > helper" subsystem. > > So the patch inlined: STIR421x support is already in the kernel. Please send a patch against Linus' or Dave Miller's tree if you have some changes. You can clone their git tree: http://kernel.org/git/ Cheers, Samuel. > > --- vanilla/irda-usb.h 2006-04-06 13:22:29 +0300 > +++ irda-usb.h 2006-04-06 15:37:36 +0300 > @@ -1,7 +1,7 @@ > /***************************************************************************** > * > * Filename: irda-usb.h > - * Version: 0.9b > + * Version: 0.10 > * Description: IrDA-USB Driver > * Status: Experimental > * Author: Dag Brattli <da...@br...> > @@ -9,6 +9,10 @@ > * Copyright (C) 2001, Roman Weissgaerber <we...@vi...> > * Copyright (C) 2000, Dag Brattli <da...@br...> > * Copyright (C) 2001, Jean Tourrilhes <jt...@hp...> > + * Copyright (C) 2004, SigmaTel, Inc. <irq...@si...> > + * SigmaTel port by 2005, Milan Beno <be...@po...> > + * 2006, Nick Fedchik <ni...@fe...> > + * Samuel Ortiz <sam...@no...> > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > @@ -79,15 +83,16 @@ > /* Inbound header */ > #define MEDIA_BUSY 0x80 > > -#define SPEED_2400 0x01 > -#define SPEED_9600 0x02 > -#define SPEED_19200 0x03 > -#define SPEED_38400 0x04 > -#define SPEED_57600 0x05 > -#define SPEED_115200 0x06 > -#define SPEED_576000 0x07 > -#define SPEED_1152000 0x08 > -#define SPEED_4000000 0x09 > +#define SPEED_2400 0x01 > +#define SPEED_9600 0x02 > +#define SPEED_19200 0x03 > +#define SPEED_38400 0x04 > +#define SPEED_57600 0x05 > +#define SPEED_115200 0x06 > +#define SPEED_576000 0x07 > +#define SPEED_1152000 0x08 > +#define SPEED_4000000 0x09 > +#define SPEED_16000000 0x0A > > /* Basic capabilities */ > #define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */ > @@ -100,11 +105,14 @@ > #define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets > */ > #define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ > #define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ > +#define IUC_STIR421X 0x80 /* SigmaTel 4210/4220/4116 VFIR Device */ > > /* USB class definitions */ > -#define USB_IRDA_HEADER 0x01 > -#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ > -#define USB_DT_IRDA 0x21 > +#define USB_IRDA_HEADER 0x01 > +#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ > +#define USB_DT_IRDA 0x21 > +#define USB_STIR421X_HEADER 0x03 /* SigmaTel STIR421X extended header */ > +#define IU_STIR421X_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + > USB_STIR421X_HEADER) > > struct irda_class_desc { > __u8 bLength; > @@ -123,6 +131,7 @@ > * (6.2.5, USB-IrDA class spec 1.0) */ > > #define IU_REQ_GET_CLASS_DESC 0x06 > +#define STIR421X_PATCH_BLOCK_SIZE 1023 > > struct irda_usb_cb { > struct irda_class_desc *irda_desc; > @@ -136,7 +145,8 @@ > __u16 bulk_out_mtu; /* Max Tx packet size in bytes */ > __u8 bulk_int_ep; /* Interrupt Endpoint assignments */ > > - struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames > */ > + __u8 max_rx_urb; > + struct urb **rx_urb; /* URBs used to receive data > frames > */ > struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */ > struct urb *tx_urb; /* URB used to send data frames */ > struct urb *speed_urb; /* URB used to send speed commands */ > @@ -156,6 +166,8 @@ > __s16 new_xbofs; /* xbofs we need to set */ > __u32 speed; /* Current speed */ > __s32 new_speed; /* speed we need to set */ > + __u8 header_length; /* USB-IrDA frame header size */ > + __s32 needspatch; /* device needs firmware patch */ > > struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ > }; > --- vanilla/irda-usb.c 2006-04-06 13:22:29 +0300 > +++ irda-usb.c 2006-05-24 12:18:39 +0300 > @@ -1,7 +1,7 @@ > /***************************************************************************** > * > * Filename: irda-usb.c > - * Version: 0.9b > + * Version: 0.10 > * Description: IrDA-USB Driver > * Status: Experimental > * Author: Dag Brattli <da...@br...> > @@ -9,7 +9,11 @@ > * Copyright (C) 2000, Roman Weissgaerber <we...@vi...> > * Copyright (C) 2001, Dag Brattli <da...@br...> > * Copyright (C) 2001, Jean Tourrilhes <jt...@hp...> > - * > + * Copyright (C) 2004, SigmaTel, Inc. <irq...@si...> > + * SigmaTel port by 2005, Milan Beno <be...@po...> > + * 2006, Nick Fedchik <ni...@fe...> > + * Samuel Ortiz <sam...@no...> > + * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > * the Free Software Foundation; either version 2 of the License, or > @@ -61,6 +65,7 @@ > #include <linux/slab.h> > #include <linux/rtnetlink.h> > #include <linux/usb.h> > +#include <linux/firmware.h> > > #include "irda-usb.h" > > @@ -78,6 +83,10 @@ > { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW > }, > /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ > { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW > }, > + /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */ > + {USB_DEVICE(0x66f, 0x4210),.driver_info = IUC_STIR421X | IUC_SPEED_BUG}, > + {USB_DEVICE(0x66f, 0x4220),.driver_info = IUC_STIR421X | IUC_SPEED_BUG}, > + {USB_DEVICE(0x66f, 0x4116),.driver_info = IUC_STIR421X | IUC_SPEED_BUG}, > { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | > USB_DEVICE_ID_MATCH_INT_SUBCLASS, > .bInterfaceClass = USB_CLASS_APP_SPEC, > @@ -99,6 +108,7 @@ > > /*------------------------------------------------------------------*/ > > +static void irda_usb_init_qos(struct irda_usb_cb *self); > static struct irda_class_desc *irda_usb_find_class_desc(struct > usb_interface > *intf); > static void irda_usb_disconnect(struct usb_interface *intf); > static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); > @@ -141,6 +151,22 @@ > __u8 *header, > int force) > { > + /* Here we check if we have an STIR421x chip, > + * and if either speed or xbofs (or both) needs > + * to be changed. > + */ > + if (self->capability & IUC_STIR421X && > + ((self->new_speed != -1) || (self->new_xbofs != -1))) { > + > + /* With STIR421x, speed and xBOFs must be set at the same > + * time, even if only one of them changes. > + */ > + if (self->new_speed == -1) > + self->new_speed = self->speed; > + > + if (self->new_xbofs == -1) > + self->new_xbofs = self->xbofs; > + } > /* Set the negotiated link speed */ > if (self->new_speed != -1) { > /* Hum... Ugly hack :-( > @@ -191,6 +217,10 @@ > *header = SPEED_4000000; > self->new_xbofs = 0; > break; > + case 16000000: > + *header = SPEED_16000000; > + self->new_xbofs = 0; > + break; > } > } else > /* No change */ > @@ -262,12 +292,19 @@ > /* Set the new speed and xbofs in this fake frame */ > irda_usb_build_header(self, frame, 1); > > + if (self->capability & IUC_STIR421X) { > + if (frame[0] == 0) > + return; // do nothing if no change > + frame[1] = 0; // other parameters don't change here > + frame[2] = 0; > + } > + > /* Submit the 0 length IrDA frame to trigger new speed settings */ > usb_fill_bulk_urb(urb, self->usbdev, > usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), > frame, IRDA_USB_SPEED_MTU, > speed_bulk_callback, self); > - urb->transfer_buffer_length = USB_IRDA_HEADER; > + urb->transfer_buffer_length = self->header_length; > urb->transfer_flags = 0; > > /* Irq disabled -> GFP_ATOMIC */ > @@ -383,16 +420,51 @@ > * allocation will be done lower in skb_push(). > * Also, we don't use directly skb_cow(), because it require > * headroom >= 16, which force unnecessary copies - Jean II */ > - if (skb_headroom(skb) < USB_IRDA_HEADER) { > + if (skb_headroom(skb) < self->header_length) { > IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); > - if (skb_cow(skb, USB_IRDA_HEADER)) { > + if (skb_cow(skb, self->header_length)) { > IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); > goto drop; > } > } > > /* Change setting for next frame */ > - irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0); > + if (self->capability & IUC_STIR421X) { > + __u16 turnaround_time; > + __u8 *frame; > + > + turnaround_time = irda_get_mtt(skb); > + frame = skb_push(skb, self->header_length); > + irda_usb_build_header(self, frame, 0); > + frame[2] = turnaround_time; > + if (turnaround_time == 0) > + frame[2] = 0; > + else if (turnaround_time <= 10) > + frame[2] = 1; > + else if (turnaround_time <= 50) > + frame[2] = 2; > + else if (turnaround_time <= 100) > + frame[2] = 3; > + else if (turnaround_time <= 500) > + frame[2] = 4; > + else if (turnaround_time <= 1000) > + frame[2] = 5; > + else if (turnaround_time <= 5000) > + frame[2] = 6; > + else > + frame[2] = 7; > + if ((skb->len != 0) && > + ((skb->len % 128) == 0) && ((skb->len % 512) != 0)) { > + /* add extra byte for special SigmaTel feature */ > + frame[1] = 1; > + skb_put(skb, 1); > + } else { > + frame[1] = 0; > + } > + } else { > + irda_usb_build_header(self, skb_push(skb, self->header_length), > + 0); > + } > > /* FIXME: Make macro out of this one */ > ((struct irda_skb_cb *)skb->cb)->context = self; > @@ -795,7 +867,7 @@ > } > > /* Check for empty frames */ > - if (urb->actual_length <= USB_IRDA_HEADER) { > + if (urb->actual_length <= self->header_length) { > IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__); > goto done; > } > @@ -816,7 +888,14 @@ > docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); > > /* Allocate a new skb */ > - newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); > + if (self->capability & IUC_STIR421X) > + newskb = > + dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU > + + USB_STIR421X_HEADER); > + else > + newskb = > + dev_alloc_skb(docopy ? urb->actual_length : > + IRDA_SKB_MAX_MTU); > if (!newskb) { > self->stats.rx_dropped++; > /* We could deliver the current skb, but this would stall > @@ -826,6 +905,7 @@ > > /* Make sure IP header get aligned (IrDA header is 5 bytes) */ > /* But IrDA-USB header is 1 byte. Jean II */ > + /* But STIR421X header is 3 bytes. Nick Fedchik */ > //skb_reserve(newskb, USB_IRDA_HEADER - 1); > > if(docopy) { > @@ -845,7 +925,7 @@ > > /* Set proper length on skb & remove USB-IrDA header */ > skb_put(dataskb, urb->actual_length); > - skb_pull(dataskb, USB_IRDA_HEADER); > + skb_pull(dataskb, self->header_length); > > /* Ask the networking layer to queue the packet for the IrDA stack */ > dataskb->dev = self->netdev; > @@ -936,6 +1016,175 @@ > return 0; /* For now */ > } > > +#define STIR421X_PATCH_PRODUCT_VER "Product Version: " > +// #define STIR421X_PATCH_COMPONENT_VER "Component Version: " //While > it > never used > +#define STIR421X_PATCH_STMP_TAG "STMP" > +#define STIR421X_PATCH_CODE_OFFSET 512 /* patch image starts before here > */ > +#define STIR421X_PATCH_END_OF_HDR_TAG 0x1A /* marks end of patch file > header > (PC DOS text file EOF character) */ > +#define FIRMWARE_IO_DELAY 20 > +/* > + * Known firmware patches for STIR421x dongles > + */ > +static char *stir421x_patches[] = { > + "42101001.sb", > + "42101002.sb", > +}; > + > +/* > + * Function stir421x_get_patch_version(const struct firmware *fw) > + * > + * Get SigmaTel patch version from firmware code > + */ > +static int stir421x_getfwver(const struct firmware *fw) > +{ > + unsigned int ver_offset=0; > + unsigned long version_major, version_minor, version_build; > + unsigned char *version_start; > + int version_found = 0; > + > + for (ver_offset = 0; > + ver_offset < fw->size; ver_offset++) { > + if (!memcmp(fw->data + ver_offset, > + STIR421X_PATCH_PRODUCT_VER, > + sizeof(STIR421X_PATCH_PRODUCT_VER) - 1)) { > + version_found = 1; > + version_start = > + fw->data + ver_offset + > + sizeof(STIR421X_PATCH_PRODUCT_VER) - 1; > + break; > + } > + } > + /* We couldn't find a product version on this patch */ > + if (!version_found) > + return -EINVAL; > + /* Let's check if the product version is dotted */ > + if (version_start[3] != '.' || version_start[7] != '.') > + return -EINVAL; > + version_major = simple_strtoul(version_start, NULL, 10); > + version_minor = simple_strtoul(version_start + 4, NULL, 10); > + version_build = simple_strtoul(version_start + 8, NULL, 10); > + IRDA_DEBUG(3,"%s(): Firmware version %ld.%ld.%ld found!\n", > + __FUNCTION__, version_major, version_minor, version_build); > + > + return (((version_major) << 12) + > + ((version_minor) << 8) + > + ((version_build / 10) << 4) + (version_build % 10)); > +} > + > +/* > + * Function stir421x_fwupload (struct irda_usb_cb *self, > + * unsigned char *patch, > + * const unsigned int patch_len) > + * > + * Upload firmware patch to SigmaTel IRDA-USB dongle > + */ > +static int stir421x_fwupload(struct irda_usb_cb *self, > + unsigned char *patch, const unsigned int patch_len) > +{ > + int ret = 0; > + int actual_len = 0; > + unsigned int i = 0; > + unsigned int block_size = 0; > + unsigned char *patch_block; > + > + patch_block = kzalloc(STIR421X_PATCH_BLOCK_SIZE, GFP_KERNEL); > + if (NULL == patch_block) { > + IRDA_ERROR("%s(): No mem for firmware\n",__FUNCTION__); > + return -ENOMEM; > + } > + /* break up patch into 1023-byte sections */ > + for (i = 0; i < patch_len; i += block_size) { > + block_size = patch_len - i; > + if (block_size > STIR421X_PATCH_BLOCK_SIZE) > + block_size = STIR421X_PATCH_BLOCK_SIZE; > + /* upload the patch section */ > + memcpy(patch_block, patch + i, block_size); > + ret = usb_bulk_msg(self->usbdev, > + usb_sndbulkpipe(self->usbdev, > + self->bulk_out_ep), > + patch_block, block_size, > + &actual_len, msecs_to_jiffies(500)); > + printk("%s(): Uploaded %u bytes of patch (ret=%d)\n", > + __FUNCTION__, actual_len, ret); > + if (ret < 0) > + break; > + } > + if (ret < 0) > + IRDA_ERROR("%s(): firmware upload failed, return %d\n", > + __FUNCTION__, ret); > + kfree(patch_block); > + > + return ret; > +} > + > + > +/* > + * Function stir421x_patching(struct irda_usb_cb *self) > + * > + * Get a firmware code from userspase using hotplug request_firmware() > call > + */ > + > +static int stir421x_patching(struct irda_usb_cb *self) > +{ > + unsigned int i; > + int ret; > + static const struct firmware *fw; > + > + for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) { > + ret = request_firmware(&fw, stir421x_patches[i], > + &self->usbdev->dev); > + if (ret < 0) > + continue; // See the _request_firmware() internals > + /* We get a patch from userspace */ > + IRDA_MESSAGE("%s(): Received firmware %s (%u bytes)\n", > + __FUNCTION__, stir421x_patches[i], fw->size); > + ret = stir421x_getfwver(fw); > + if (ret != self->usbdev->descriptor.bcdDevice) { > + /* Couldn't fetch a version, let's move on to the next file */ > + IRDA_WARNING("%s(): Firmware ver %d <> bcdDevice %d\n", > + __FUNCTION__, ret, > + self->usbdev->descriptor.bcdDevice); > + ret = -EINVAL; > + release_firmware(fw); > + } else { > + /* If we're here, we've found a correct patch */ > + ret = 0; > + break; > + } > + } > + /* We couldn't find a valid firmware, let's leave */ > + if (ret < 0) { > + IRDA_ERROR("%s(): No valid firmware found, return %d\n", > + __FUNCTION__, ret); > + return ret; > + } > + /* The actual image starts after the "STMP" keyword */ > + ret = -ENODATA; > + i = 0; > + /* forward to the firmware header tag */ > + while ((fw->data[i] != STIR421X_PATCH_END_OF_HDR_TAG) && (i < fw->size)) > + i++; > + /* here we check for the out of buffer case */ > + if ((STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i]) > + && (i < (fw->size - sizeof(STIR421X_PATCH_STMP_TAG)))) > + if (!memcmp(fw->data + i + 1, STIR421X_PATCH_STMP_TAG, > + sizeof(STIR421X_PATCH_STMP_TAG) - 1)) > + ret = 0; > + /* We couldn't find "STMP" tag from the header */ > + if (-ENODATA == ret) { > + IRDA_ERROR("%s(): No firmware tag found (return %d)\n", > + __FUNCTION__, ret); > + } else { > + /* Let's upload the patch to the target */ > + i += sizeof(STIR421X_PATCH_STMP_TAG); > + ret = stir421x_fwupload(self, &fw->data[i], fw->size - i); > + } > + release_firmware(fw); > + > + return ret; > +} > + > + > /********************** IRDA DEVICE CALLBACKS **********************/ > /* > * Main calls from the IrDA/Network subsystem. > @@ -966,11 +1215,14 @@ > IRDA_ASSERT(self != NULL, return -1;); > > /* Can only open the device if it's there */ > - if(!self->present) { > + if (!self->present) { > IRDA_WARNING("%s(), device not present!\n", __FUNCTION__); > - return -1; > + return -1; // why not a -ENODEV? Nick Fedchik > + } > + if (self->needspatch) { > + IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__); > + return -EIO; > } > - > /* Initialise default speed and xbofs value > * (IrLAP will change that soon) */ > self->speed = -1; > @@ -1049,7 +1301,7 @@ > del_timer(&self->rx_defer_timer); > > /* Deallocate all the Rx path buffers (URBs and skb) */ > - for (i = 0; i < IU_MAX_RX_URBS; i++) { > + for (i = 0; i < self->max_rx_urb; i++) { > struct urb *urb = self->rx_urb[i]; > struct sk_buff *skb = (struct sk_buff *) urb->context; > /* Cancel the receive command */ > @@ -1161,8 +1413,9 @@ > self->qos.window_size.bits = desc->bmWindowSize; > self->qos.data_size.bits = desc->bmDataSize; > > - IRDA_DEBUG(0, "%s(), dongle says speed=0x%X, size=0x%X, window=0x%X, > bofs=0x%X, turn=0x%X\n", > - __FUNCTION__, self->qos.baud_rate.bits, self->qos.data_size.bits, > self->qos.window_size.bits, self->qos.additional_bofs.bits, > self->qos.min_turn_time.bits); > + IRDA_DEBUG(0, "%s(): dongle says speed=%ubps, size=%db, window=%db, > bofs=%d, > turn=%d\n", > + __FUNCTION__, self->qos.baud_rate.bits, self->qos.data_size.bits, > self->qos.window_size.bits, > + self->qos.additional_bofs.bits, self->qos.min_turn_time.bits); > > /* Don't always trust what the dongle tell us */ > if(self->capability & IUC_SIR_ONLY) > @@ -1295,7 +1548,7 @@ > } > } > > - IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), > int=%02X\n", > + IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (MTU %d), > int=%02X\n", > __FUNCTION__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, > self->bulk_int_ep); > /* Should be 8, 16, 32 or 64 bytes */ > IRDA_ASSERT(self->bulk_out_mtu == 64, ;); > @@ -1424,9 +1677,20 @@ > self->netdev = net; > spin_lock_init(&self->lock); > init_timer(&self->rx_defer_timer); > + self->capability = id->driver_info; > + self->needspatch = ((self->capability & IUC_STIR421X) != 0); > > /* Create all of the needed urbs */ > - for (i = 0; i < IU_MAX_RX_URBS; i++) { > + if (self->capability & IUC_STIR421X) { > + self->max_rx_urb = IU_STIR421X_MAX_RX_URBS; > + self->header_length = USB_STIR421X_HEADER; > + } else { > + self->max_rx_urb = IU_MAX_RX_URBS; > + self->header_length = USB_IRDA_HEADER; > + } > + self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *), > + GFP_KERNEL); > + for (i = 0; i < self->max_rx_urb; i++) { > self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); > if (!self->rx_urb[i]) { > goto err_out_1; > @@ -1477,18 +1741,28 @@ > ret = -EIO; > goto err_out_3; > } > + self->usbdev = dev; > > /* Find IrDA class descriptor */ > irda_desc = irda_usb_find_class_desc(intf); > ret = -ENODEV; > if (irda_desc == NULL) > goto err_out_3; > + if (self->needspatch) { > + ret = > + usb_control_msg(self->usbdev, > + usb_sndctrlpipe(self->usbdev, 0), 0x02, > + 0x40, 0, 0, 0, 0, msecs_to_jiffies(500)); > + if (ret < 0) { > + IRDA_ERROR("%s(): usb_control_msg failed %d\n", > + __FUNCTION__, ret); > + goto err_out_3; > + } > + } > > self->irda_desc = irda_desc; > self->present = 1; > self->netopen = 0; > - self->capability = id->driver_info; > - self->usbdev = dev; > self->usbintf = intf; > > /* Allocate the buffer for speed changes */ > @@ -1507,8 +1781,31 @@ > > IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); > usb_set_intfdata(intf, self); > + if (self->needspatch) { > + /* Now we fetch and upload the firmware patch */ > + ret = stir421x_patching(self); > + self->needspatch = (ret < 0); > + if (self->needspatch) { > + IRDA_ERROR("STIR421X: No firmware found for device %s\n", net->name); > + goto err_out_5; > + } > + /* replace IrDA class descriptor with what > + * patched device is now reporting > + */ > + irda_desc = irda_usb_find_class_desc(self->usbintf); > + if (NULL == irda_desc) { > + ret = -ENODEV; > + goto err_out_5; > + } > + if (self->irda_desc) > + kfree(self->irda_desc); > + self->irda_desc = irda_desc; > + irda_usb_init_qos(self); > + } > return 0; > > +err_out_5: > + unregister_netdev(self->netdev); > err_out_4: > kfree(self->speed_buff); > err_out_3: > @@ -1517,10 +1814,11 @@ > err_out_2: > usb_free_urb(self->tx_urb); > err_out_1: > - for (i = 0; i < IU_MAX_RX_URBS; i++) { > + for (i = 0; i < self->max_rx_urb; i++) { > if (self->rx_urb[i]) > usb_free_urb(self->rx_urb[i]); > } > + IRDA_MESSAGE("IrDA: Unregistering device %s\n", net->name); > free_netdev(net); > err_out: > return ret; > @@ -1570,7 +1868,7 @@ > /*netif_device_detach(self->netdev);*/ > netif_stop_queue(self->netdev); > /* Stop all the receive URBs. Must be synchronous. */ > - for (i = 0; i < IU_MAX_RX_URBS; i++) > + for (i = 0; i < self->max_rx_urb; i++) > usb_kill_urb(self->rx_urb[i]); > /* Cancel Tx and speed URB. > * Make sure it's synchronous to avoid races. */ > @@ -1585,8 +1883,9 @@ > self->usbintf = NULL; > > /* Clean up our urbs */ > - for (i = 0; i < IU_MAX_RX_URBS; i++) > + for (i = 0; i < self->max_rx_urb; i++) > usb_free_urb(self->rx_urb[i]); > + kfree(self->rx_urb); > /* Clean up Tx and speed URB */ > usb_free_urb(self->tx_urb); > usb_free_urb(self->speed_urb); > @@ -1647,6 +1946,6 @@ > */ > module_param(qos_mtt_bits, int, 0); > MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); > -MODULE_AUTHOR("Roman Weissgaerber <we...@vi...>, Dag Brattli > <da...@br...> and Jean Tourrilhes <jt...@hp...>"); > -MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); > +MODULE_AUTHOR("Linux IRDA-USB Support Team > <ird...@li...>"); > +MODULE_DESCRIPTION("IrDA-USB FIR/VFIR Dongle Driver, 2006"); > MODULE_LICENSE("GPL"); > > > > -- > Best Regards, > Nick Fedchik > > > ------------------------------------------------------- > All the advantages of Linux Managed Hosting--Without the Cost and Risk! > Fully trained technicians. The highest number of Red Hat certifications in > the hosting industry. Fanatical Support. Click to learn more > http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642 > _______________________________________________ > irda-users mailing list > ird...@li... > http://lists.sourceforge.net/lists/listinfo/irda-users > |