kingsun-sir.c revision 66f5e51ed5a300291b34bf3e2b1e22ac28ca3631
1a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/***************************************************************************** 2a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* 3a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* Filename: kingsun-sir.c 4a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* Version: 0.1.1 5a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* Description: Irda KingSun/DonShine USB Dongle 6a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* Status: Experimental 766f5e51ed5a300291b34bf3e2b1e22ac28ca3631Samuel Ortiz* Author: Alex Villacís Lasso <a_villacis@palosanto.com> 8a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* 9a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* Based on stir4200 and mcs7780 drivers, with (strange?) differences 10a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* 11a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* This program is free software; you can redistribute it and/or modify 12a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* it under the terms of the GNU General Public License as published by 13a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* the Free Software Foundation; either version 2 of the License. 14a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* 15a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* This program is distributed in the hope that it will be useful, 16a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* but WITHOUT ANY WARRANTY; without even the implied warranty of 17a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* GNU General Public License for more details. 19a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* 20a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* You should have received a copy of the GNU General Public License 21a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* along with this program; if not, write to the Free Software 22a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso* 24a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso*****************************************************************************/ 25a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 26a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 27a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * This is my current (2007-04-25) understanding of how this dongle is supposed 28a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * to work. This is based on reverse-engineering and examination of the packet 29a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * data sent and received by the WinXP driver using USBSnoopy. Feel free to 30a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * update here as more of this dongle is known: 31a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 32a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * General: Unlike the other USB IrDA dongles, this particular dongle exposes, 33a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * not two bulk (in and out) endpoints, but two *interrupt* ones. This dongle, 34a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * like the bulk based ones (stir4200.c and mcs7780.c), requires polling in 35a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * order to receive data. 36a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Transmission: Just like stir4200, this dongle uses a raw stream of data, 37a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * which needs to be wrapped and escaped in a similar way as in stir4200.c. 38a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Reception: Poll-based, as in stir4200. Each read returns the contents of a 39a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 8-byte buffer, of which the first byte (LSB) indicates the number of bytes 40a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * (1-7) of valid data contained within the remaining 7 bytes. For example, if 41a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * the buffer had the following contents: 42a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 06 ff ff ff c0 01 04 aa 43a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * This means that (06) there are 6 bytes of valid data. The byte 0xaa at the 44a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * end is garbage (left over from a previous reception) and is discarded. 45a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * If a read returns an "impossible" value as the length of valid data (such as 46a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 0x36) in the first byte, then the buffer is uninitialized (as is the case of 47a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * first plug-in) and its contents should be discarded. There is currently no 48a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * evidence that the top 5 bits of the 1st byte of the buffer can have values 49a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * other than 0 once reception begins. 50a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Once valid bytes are collected, the assembled stream is a sequence of 51a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * wrapped IrDA frames that is unwrapped and unescaped as in stir4200.c. 52a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * BIG FAT WARNING: the dongle does *not* reset the RX buffer in any way after 53a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * a successful read from the host, which means that in absence of further 54a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * reception, repeated reads from the dongle will return the exact same 55a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * contents repeatedly. Attempts to be smart and cache a previous read seem 56a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * to result in corrupted packets, so this driver depends on the unwrap logic 57a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * to sort out any repeated reads. 58a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Speed change: no commands observed so far to change speed, assumed fixed 59a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 9600bps (SIR). 60a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 61a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 62a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/module.h> 63a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/moduleparam.h> 64a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/kernel.h> 65a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/types.h> 66a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/errno.h> 67a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/init.h> 68a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/slab.h> 69a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/module.h> 70a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/kref.h> 71a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/usb.h> 72a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/device.h> 73a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/crc32.h> 74a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 75a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <asm/unaligned.h> 76a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <asm/byteorder.h> 77a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <asm/uaccess.h> 78a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 79a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <net/irda/irda.h> 80a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <net/irda/wrapper.h> 81a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <net/irda/crc.h> 82a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 83a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 84a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * According to lsusb, 0x07c0 is assigned to 85a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * "Code Mercenaries Hard- und Software GmbH" 86a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 87a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KING_VENDOR_ID 0x07c0 88a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KING_PRODUCT_ID 0x4200 89a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 90a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* These are the currently known USB ids */ 91a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic struct usb_device_id dongles[] = { 92a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* KingSun Co,Ltd IrDA/USB Bridge */ 93a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) }, 94a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso { } 95a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso}; 96a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 97a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s LassoMODULE_DEVICE_TABLE(usb, dongles); 98a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 99a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_MTT 0x07 100a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 101a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_FIFO_SIZE 4096 102a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_EP_IN 0 103a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_EP_OUT 1 104a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 105a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostruct kingsun_cb { 106a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_device *usbdev; /* init: probe_irda */ 107a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct net_device *netdev; /* network layer */ 108a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct irlap_cb *irlap; /* The link layer we are binded to */ 109a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct net_device_stats stats; /* network statistics */ 110a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct qos_info qos; 111a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 112a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 *in_buf; /* receive buffer */ 113a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 *out_buf; /* transmit buffer */ 114a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 max_rx; /* max. atomic read from dongle 115a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso (usually 8), also size of in_buf */ 116a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 max_tx; /* max. atomic write to dongle 117a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso (usually 8) */ 118a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 119a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso iobuff_t rx_buff; /* receive unwrap state machine */ 120a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct timeval rx_time; 121a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso spinlock_t lock; 122a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int receiving; 123a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 124a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_in; 125a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_out; 126a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 127a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct urb *tx_urb; 128a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct urb *rx_urb; 129a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso}; 130a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 131a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* Callback transmission routine */ 132a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic void kingsun_send_irq(struct urb *urb) 133a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 134a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = urb->context; 135a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct net_device *netdev = kingsun->netdev; 136a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 137a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* in process of stopping, just drop data */ 138a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!netif_running(kingsun->netdev)) { 139a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun_send_irq: Network not running!"); 140a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 141a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 142a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 143a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* unlink, shutdown, unplug, other nasties */ 144a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (urb->status != 0) { 145a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun_send_irq: urb asynchronously failed - %d", 146a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso urb->status); 147a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 148a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_wake_queue(netdev); 149a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 150a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 151a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 152a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Called from net/core when new frame is available. 153a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 154a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev) 155a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 156a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun; 157a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int wraplen; 158a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int ret = 0; 159a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 160a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (skb == NULL || netdev == NULL) 161a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -EINVAL; 162a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 163a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_stop_queue(netdev); 164a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 165a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* the IRDA wrapping routines don't deal with non linear skb */ 166a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso SKB_LINEAR_ASSERT(skb); 167a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 168a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun = netdev_priv(netdev); 169a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 170a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso spin_lock(&kingsun->lock); 171a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 172a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Append data to the end of whatever data remains to be transmitted */ 173a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso wraplen = async_wrap_skb(skb, 174a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->out_buf, 175a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso KINGSUN_FIFO_SIZE); 176a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 177a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Calculate how much data can be transmitted in this urb */ 178a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, 179a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), 180a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->out_buf, wraplen, kingsun_send_irq, 181a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun, 1); 182a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 183a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) { 184a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun_hard_xmit: failed tx_urb submit: %d", ret); 185a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso switch (ret) { 186a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso case -ENODEV: 187a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso case -EPIPE: 188a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso break; 189a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso default: 190a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->stats.tx_errors++; 191a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_start_queue(netdev); 192a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 193a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } else { 194a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->stats.tx_packets++; 195a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->stats.tx_bytes += skb->len; 196a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 197a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 198a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso dev_kfree_skb(skb); 199a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso spin_unlock(&kingsun->lock); 200a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 201a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return ret; 202a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 203a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 204a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* Receive callback function */ 205a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic void kingsun_rcv_irq(struct urb *urb) 206a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 207a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = urb->context; 208a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int ret; 209a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 210a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* in process of stopping, just drop data */ 211a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!netif_running(kingsun->netdev)) { 212a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 213a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 214a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 215a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 216a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* unlink, shutdown, unplug, other nasties */ 217a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (urb->status != 0) { 218a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun_rcv_irq: urb asynchronously failed - %d", 219a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso urb->status); 220a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 221a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 222a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 223a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 224a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (urb->actual_length == kingsun->max_rx) { 225a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 *bytes = urb->transfer_buffer; 226a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int i; 227a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 228a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* The very first byte in the buffer indicates the length of 229a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso valid data in the read. This byte must be in the range 230a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 1..kingsun->max_rx -1 . Values outside this range indicate 231a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso an uninitialized Rx buffer when the dongle has just been 232a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso plugged in. */ 233a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) { 234a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso for (i = 1; i <= bytes[0]; i++) { 235a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso async_unwrap_char(kingsun->netdev, 236a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso &kingsun->stats, 237a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso &kingsun->rx_buff, bytes[i]); 238a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 239a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->netdev->last_rx = jiffies; 240a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso do_gettimeofday(&kingsun->rx_time); 241a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 242a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso (kingsun->rx_buff.state != OUTSIDE_FRAME) 243a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ? 1 : 0; 244a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 245a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } else if (urb->actual_length > 0) { 246a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("%s(): Unexpected response length, expected %d got %d", 247a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __FUNCTION__, kingsun->max_rx, urb->actual_length); 248a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 249a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* This urb has already been filled in kingsun_net_open */ 250a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ret = usb_submit_urb(urb, GFP_ATOMIC); 251a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 252a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 253a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 254a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Function kingsun_net_open (dev) 255a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 256a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Network device is taken up. Usually this is done by "ifconfig irda0 up" 257a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 258a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_net_open(struct net_device *netdev) 259a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 260a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = netdev_priv(netdev); 261a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int err = -ENOMEM; 262a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso char hwname[16]; 263a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 264a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */ 265a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 266a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 267a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Initialize for SIR to copy data directly into skb. */ 268a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.in_frame = FALSE; 269a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.state = OUTSIDE_FRAME; 270a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU; 271a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); 272a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->rx_buff.skb) 273a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 274a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 275a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso skb_reserve(kingsun->rx_buff.skb, 1); 276a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.head = kingsun->rx_buff.skb->data; 277a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso do_gettimeofday(&kingsun->rx_time); 278a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 279a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); 280a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->rx_urb) 281a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 282a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 283a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); 284a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->tx_urb) 285a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 286a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 287a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* 288a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Now that everything should be initialized properly, 289a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Open new IrLAP layer instance to take care of us... 290a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 291a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); 292a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); 293a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->irlap) { 294a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun-sir: irlap_open failed"); 295a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 296a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 297a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 298a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Start first reception */ 299a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, 300a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), 301a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->in_buf, kingsun->max_rx, 302a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun_rcv_irq, kingsun, 1); 303a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb->status = 0; 304a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 305a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (err) { 306a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun-sir: first urb-submit failed: %d", err); 307a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto close_irlap; 308a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 309a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 310a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_start_queue(netdev); 311a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 312a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Situation at this point: 313a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - all work buffers allocated 314a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - urbs allocated and ready to fill 315a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - max rx packet known (in max_rx) 316a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - unwrap state machine initialized, in state outside of any frame 317a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - receive request in progress 318a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - IrLAP layer started, about to hand over packets to send 319a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 320a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 321a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 322a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 323a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso close_irlap: 324a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso irlap_close(kingsun->irlap); 325a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso free_mem: 326a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->tx_urb) { 327a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->tx_urb); 328a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->tx_urb = NULL; 329a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 330a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_urb) { 331a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->rx_urb); 332a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb = NULL; 333a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 334a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_buff.skb) { 335a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kfree_skb(kingsun->rx_buff.skb); 336a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.skb = NULL; 337a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.head = NULL; 338a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 339a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return err; 340a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 341a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 342a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 343a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Function kingsun_net_close (kingsun) 344a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 345a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Network device is taken down. Usually this is done by 346a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * "ifconfig irda0 down" 347a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 348a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_net_close(struct net_device *netdev) 349a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 350a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = netdev_priv(netdev); 351a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 352a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Stop transmit processing */ 353a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_stop_queue(netdev); 354a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 355a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Mop up receive && transmit urb's */ 356a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_kill_urb(kingsun->tx_urb); 357a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_kill_urb(kingsun->rx_urb); 358a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 359a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->tx_urb); 360a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->rx_urb); 361a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 362a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->tx_urb = NULL; 363a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb = NULL; 364a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 365a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kfree_skb(kingsun->rx_buff.skb); 366a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.skb = NULL; 367a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.head = NULL; 368a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.in_frame = FALSE; 369a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.state = OUTSIDE_FRAME; 370a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 371a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 372a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Stop and remove instance of IrLAP */ 373a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->irlap) 374a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso irlap_close(kingsun->irlap); 375a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 376a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->irlap = NULL; 377a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 378a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 379a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 380a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 381a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 382a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * IOCTLs : Extra out-of-band network commands... 383a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 384a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq, 385a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int cmd) 386a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 387a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct if_irda_req *irq = (struct if_irda_req *) rq; 388a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = netdev_priv(netdev); 389a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int ret = 0; 390a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 391a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso switch (cmd) { 392a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso case SIOCSBANDWIDTH: /* Set bandwidth */ 393a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!capable(CAP_NET_ADMIN)) 394a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -EPERM; 395a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 396a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Check if the device is still there */ 397a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (netif_device_present(kingsun->netdev)) 398a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* No observed commands for speed change */ 399a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ret = -EOPNOTSUPP; 400a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso break; 401a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 402a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso case SIOCSMEDIABUSY: /* Set media busy */ 403a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!capable(CAP_NET_ADMIN)) 404a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -EPERM; 405a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 406a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Check if the IrDA stack is still there */ 407a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (netif_running(kingsun->netdev)) 408a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso irda_device_set_media_busy(kingsun->netdev, TRUE); 409a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso break; 410a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 411a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso case SIOCGRECEIVING: 412a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Only approximately true */ 413a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso irq->ifr_receiving = kingsun->receiving; 414a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso break; 415a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 416a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso default: 417a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ret = -EOPNOTSUPP; 418a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 419a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 420a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return ret; 421a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 422a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 423a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 424a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Get device stats (for /proc/net/dev and ifconfig) 425a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 426a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic struct net_device_stats * 427a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassokingsun_net_get_stats(struct net_device *netdev) 428a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 429a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = netdev_priv(netdev); 430a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return &kingsun->stats; 431a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 432a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 433a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 434a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * This routine is called by the USB subsystem for each new device 435a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * in the system. We need to check if the device is ours, and in 436a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * this case start handling it. 437a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 438a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_probe(struct usb_interface *intf, 439a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso const struct usb_device_id *id) 440a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 441a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_host_interface *interface; 442a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_endpoint_descriptor *endpoint; 443a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 444a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_device *dev = interface_to_usbdev(intf); 445a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = NULL; 446a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct net_device *net = NULL; 447a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int ret = -ENOMEM; 448a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int pipe, maxp_in, maxp_out; 449a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_in; 450a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_out; 451a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 452a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Check that there really are two interrupt endpoints. 453a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso Check based on the one in drivers/usb/input/usbmouse.c 454a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 455a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso interface = intf->cur_altsetting; 456a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (interface->desc.bNumEndpoints != 2) { 457a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun-sir: expected 2 endpoints, found %d", 458a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso interface->desc.bNumEndpoints); 459a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -ENODEV; 460a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 461a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; 462a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!usb_endpoint_is_int_in(endpoint)) { 463a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun-sir: endpoint 0 is not interrupt IN"); 464a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -ENODEV; 465a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 466a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 467a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ep_in = endpoint->bEndpointAddress; 468a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso pipe = usb_rcvintpipe(dev, ep_in); 469a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 470a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (maxp_in > 255 || maxp_in <= 1) { 471a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("%s: endpoint 0 has max packet size %d not in range", 472a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __FILE__, maxp_in); 473a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -ENODEV; 474a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 475a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 476a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; 477a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!usb_endpoint_is_int_out(endpoint)) { 478a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err("kingsun-sir: endpoint 1 is not interrupt OUT"); 479a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -ENODEV; 480a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 481a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 482a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ep_out = endpoint->bEndpointAddress; 483a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso pipe = usb_sndintpipe(dev, ep_out); 484a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 485a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 486a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Allocate network device container. */ 487a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso net = alloc_irdadev(sizeof(*kingsun)); 488a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if(!net) 489a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto err_out1; 490a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 491a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso SET_MODULE_OWNER(net); 492a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso SET_NETDEV_DEV(net, &intf->dev); 493a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun = netdev_priv(net); 494a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->irlap = NULL; 495a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->tx_urb = NULL; 496a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb = NULL; 497a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->ep_in = ep_in; 498a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->ep_out = ep_out; 499a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->in_buf = NULL; 500a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->out_buf = NULL; 501a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->max_rx = (__u8)maxp_in; 502a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->max_tx = (__u8)maxp_out; 503a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->netdev = net; 504a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->usbdev = dev; 505a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.in_frame = FALSE; 506a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.state = OUTSIDE_FRAME; 507a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.skb = NULL; 508a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 509a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso spin_lock_init(&kingsun->lock); 510a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 511a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Allocate input buffer */ 512a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->in_buf = (__u8 *)kmalloc(kingsun->max_rx, GFP_KERNEL); 513a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->in_buf) 514a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 515a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 516a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Allocate output buffer */ 517a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->out_buf = (__u8 *)kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); 518a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->out_buf) 519a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 520a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 521a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, " 522a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso "Vendor: %x, Product: %x\n", 523a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso dev->devnum, le16_to_cpu(dev->descriptor.idVendor), 524a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso le16_to_cpu(dev->descriptor.idProduct)); 525a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 526a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Initialize QoS for this device */ 527a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso irda_init_max_qos_capabilies(&kingsun->qos); 528a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 529a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* That's the Rx capability. */ 530a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->qos.baud_rate.bits &= IR_9600; 531a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; 532a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso irda_qos_bits_to_value(&kingsun->qos); 533a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 534a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Override the network functions we need to use */ 535a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso net->hard_start_xmit = kingsun_hard_xmit; 536a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso net->open = kingsun_net_open; 537a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso net->stop = kingsun_net_close; 538a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso net->get_stats = kingsun_net_get_stats; 539a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso net->do_ioctl = kingsun_net_ioctl; 540a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 541a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ret = register_netdev(net); 542a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (ret != 0) 543a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 544a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 545a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso info("IrDA: Registered KingSun/DonShine device %s", net->name); 546a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 547a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_set_intfdata(intf, kingsun); 548a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 549a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Situation at this point: 550a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - all work buffers allocated 551a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - urbs not allocated, set to NULL 552a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - max rx packet known (in max_rx) 553a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - unwrap state machine (partially) initialized, but skb == NULL 554a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 555a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 556a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 557a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 558a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassofree_mem: 559a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->out_buf) kfree(kingsun->out_buf); 560a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->in_buf) kfree(kingsun->in_buf); 561a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso free_netdev(net); 562a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassoerr_out1: 563a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return ret; 564a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 565a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 566a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 567a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * The current device is removed, the USB layer tell us to shut it down... 568a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 569a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic void kingsun_disconnect(struct usb_interface *intf) 570a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 571a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = usb_get_intfdata(intf); 572a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 573a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun) 574a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 575a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 576a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso unregister_netdev(kingsun->netdev); 577a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 578a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Mop up receive && transmit urb's */ 579a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->tx_urb != NULL) { 580a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_kill_urb(kingsun->tx_urb); 581a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->tx_urb); 582a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->tx_urb = NULL; 583a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 584a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_urb != NULL) { 585a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_kill_urb(kingsun->rx_urb); 586a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->rx_urb); 587a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb = NULL; 588a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 589a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 590a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kfree(kingsun->out_buf); 591a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kfree(kingsun->in_buf); 592a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso free_netdev(kingsun->netdev); 593a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 594a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_set_intfdata(intf, NULL); 595a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 596a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 597a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#ifdef CONFIG_PM 598a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* USB suspend, so power off the transmitter/receiver */ 599a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_suspend(struct usb_interface *intf, pm_message_t message) 600a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 601a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = usb_get_intfdata(intf); 602a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 603a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_device_detach(kingsun->netdev); 604a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb); 605a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb); 606a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 607a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 608a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 609a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* Coming out of suspend, so reset hardware */ 610a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_resume(struct usb_interface *intf) 611a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 612a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = usb_get_intfdata(intf); 613a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 614a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_urb != NULL) 615a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 616a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_device_attach(kingsun->netdev); 617a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 618a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 619a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 620a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#endif 621a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 622a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 623a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * USB device callbacks 624a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 625a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic struct usb_driver irda_driver = { 626a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .name = "kingsun-sir", 627a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .probe = kingsun_probe, 628a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .disconnect = kingsun_disconnect, 629a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .id_table = dongles, 630a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#ifdef CONFIG_PM 631a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .suspend = kingsun_suspend, 632a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .resume = kingsun_resume, 633a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#endif 634a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso}; 635a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 636a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 637a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Module insertion 638a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 639a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int __init kingsun_init(void) 640a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 641a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return usb_register(&irda_driver); 642a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 643a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassomodule_init(kingsun_init); 644a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 645a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 646a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Module removal 647a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 648a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic void __exit kingsun_cleanup(void) 649a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 650a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Deregister the driver and remove all pending instances */ 651a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_deregister(&irda_driver); 652a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 653a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassomodule_exit(kingsun_cleanup); 654a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 65566f5e51ed5a300291b34bf3e2b1e22ac28ca3631Samuel OrtizMODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>"); 656a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s LassoMODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); 657a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s LassoMODULE_LICENSE("GPL"); 658