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/slab.h> 68a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/usb.h> 69a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/device.h> 70a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <linux/crc32.h> 71a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 72a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <asm/unaligned.h> 73a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <asm/byteorder.h> 74a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <asm/uaccess.h> 75a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 76a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <net/irda/irda.h> 77a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <net/irda/wrapper.h> 78a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#include <net/irda/crc.h> 79a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 80a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 81a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * According to lsusb, 0x07c0 is assigned to 82a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * "Code Mercenaries Hard- und Software GmbH" 83a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 84a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KING_VENDOR_ID 0x07c0 85a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KING_PRODUCT_ID 0x4200 86a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 87a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* These are the currently known USB ids */ 88a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic struct usb_device_id dongles[] = { 89a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* KingSun Co,Ltd IrDA/USB Bridge */ 90a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) }, 91a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso { } 92a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso}; 93a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 94a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s LassoMODULE_DEVICE_TABLE(usb, dongles); 95a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 96a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_MTT 0x07 97a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 98a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_FIFO_SIZE 4096 99a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_EP_IN 0 100a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#define KINGSUN_EP_OUT 1 101a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 102a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostruct kingsun_cb { 103a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_device *usbdev; /* init: probe_irda */ 104a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct net_device *netdev; /* network layer */ 105a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct irlap_cb *irlap; /* The link layer we are binded to */ 106af0490810cfa159b4894ddecfc5eb2e4432fb976Stephen Hemminger 107a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct qos_info qos; 108a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 109a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 *in_buf; /* receive buffer */ 110a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 *out_buf; /* transmit buffer */ 111a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 max_rx; /* max. atomic read from dongle 112a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso (usually 8), also size of in_buf */ 113a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 max_tx; /* max. atomic write to dongle 114a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso (usually 8) */ 115a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 116a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso iobuff_t rx_buff; /* receive unwrap state machine */ 117a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct timeval rx_time; 118a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso spinlock_t lock; 119a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int receiving; 120a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 121a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_in; 122a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_out; 123a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 124a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct urb *tx_urb; 125a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct urb *rx_urb; 126a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso}; 127a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 128a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* Callback transmission routine */ 129a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic void kingsun_send_irq(struct urb *urb) 130a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 131a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = urb->context; 132a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct net_device *netdev = kingsun->netdev; 133a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 134a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* in process of stopping, just drop data */ 135a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!netif_running(kingsun->netdev)) { 1366f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&kingsun->usbdev->dev, 1376f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "kingsun_send_irq: Network not running!\n"); 138a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 139a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 140a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 141a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* unlink, shutdown, unplug, other nasties */ 142a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (urb->status != 0) { 1436f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&kingsun->usbdev->dev, 1446f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "kingsun_send_irq: urb asynchronously failed - %d\n", 1456f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman urb->status); 146a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 147a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_wake_queue(netdev); 148a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 149a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 150a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 151a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Called from net/core when new frame is available. 152a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 1536518bbb803fe02b15a3211c8db2afdff0ac4f808Stephen Hemmingerstatic netdev_tx_t kingsun_hard_xmit(struct sk_buff *skb, 1546518bbb803fe02b15a3211c8db2afdff0ac4f808Stephen Hemminger 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 netif_stop_queue(netdev); 161a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 162a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* the IRDA wrapping routines don't deal with non linear skb */ 163a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso SKB_LINEAR_ASSERT(skb); 164a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 165a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun = netdev_priv(netdev); 166a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 167a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso spin_lock(&kingsun->lock); 168a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 169a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Append data to the end of whatever data remains to be transmitted */ 170a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso wraplen = async_wrap_skb(skb, 171a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->out_buf, 172a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso KINGSUN_FIFO_SIZE); 173a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 174a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Calculate how much data can be transmitted in this urb */ 175a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, 176a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), 177a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->out_buf, wraplen, kingsun_send_irq, 178a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun, 1); 179a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 180a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) { 1816f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&kingsun->usbdev->dev, 1826f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "kingsun_hard_xmit: failed tx_urb submit: %d\n", ret); 183a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso switch (ret) { 184a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso case -ENODEV: 185a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso case -EPIPE: 186a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso break; 187a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso default: 188af0490810cfa159b4894ddecfc5eb2e4432fb976Stephen Hemminger netdev->stats.tx_errors++; 189a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_start_queue(netdev); 190a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 191a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } else { 192af0490810cfa159b4894ddecfc5eb2e4432fb976Stephen Hemminger netdev->stats.tx_packets++; 193af0490810cfa159b4894ddecfc5eb2e4432fb976Stephen Hemminger netdev->stats.tx_bytes += skb->len; 194a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 195a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 196a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso dev_kfree_skb(skb); 197a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso spin_unlock(&kingsun->lock); 198a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 1994bd73ae2682d9069746bb049a416d9ab90c6684bPatrick McHardy return NETDEV_TX_OK; 200a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 201a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 202a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* Receive callback function */ 203a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic void kingsun_rcv_irq(struct urb *urb) 204a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 205a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = urb->context; 206a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int ret; 207a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 208a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* in process of stopping, just drop data */ 209a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!netif_running(kingsun->netdev)) { 210a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 211a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 212a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 213a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 214a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* unlink, shutdown, unplug, other nasties */ 215a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (urb->status != 0) { 2166f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&kingsun->usbdev->dev, 2176f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "kingsun_rcv_irq: urb asynchronously failed - %d\n", 2186f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman urb->status); 219a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 220a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 221a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 222a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 223a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (urb->actual_length == kingsun->max_rx) { 224a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 *bytes = urb->transfer_buffer; 225a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int i; 226a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 227a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* The very first byte in the buffer indicates the length of 228a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso valid data in the read. This byte must be in the range 229a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 1..kingsun->max_rx -1 . Values outside this range indicate 230a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso an uninitialized Rx buffer when the dongle has just been 231a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso plugged in. */ 232a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) { 233a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso for (i = 1; i <= bytes[0]; i++) { 234a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso async_unwrap_char(kingsun->netdev, 235af0490810cfa159b4894ddecfc5eb2e4432fb976Stephen Hemminger &kingsun->netdev->stats, 236a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso &kingsun->rx_buff, bytes[i]); 237a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 238a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso do_gettimeofday(&kingsun->rx_time); 239a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 240a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso (kingsun->rx_buff.state != OUTSIDE_FRAME) 241a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ? 1 : 0; 242a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 243a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } else if (urb->actual_length > 0) { 2446f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&kingsun->usbdev->dev, 2456f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "%s(): Unexpected response length, expected %d got %d\n", 2466f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman __func__, kingsun->max_rx, urb->actual_length); 247a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 248a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* This urb has already been filled in kingsun_net_open */ 249a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ret = usb_submit_urb(urb, GFP_ATOMIC); 250a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 251a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 252a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 253a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Function kingsun_net_open (dev) 254a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * 255a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Network device is taken up. Usually this is done by "ifconfig irda0 up" 256a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 257a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_net_open(struct net_device *netdev) 258a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 259a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = netdev_priv(netdev); 260a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int err = -ENOMEM; 261a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso char hwname[16]; 262a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 263a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */ 264a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->receiving = 0; 265a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 266a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Initialize for SIR to copy data directly into skb. */ 267a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.in_frame = FALSE; 268a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.state = OUTSIDE_FRAME; 269a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU; 270a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); 271a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->rx_buff.skb) 272a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 273a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 274a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso skb_reserve(kingsun->rx_buff.skb, 1); 275a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_buff.head = kingsun->rx_buff.skb->data; 276a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso do_gettimeofday(&kingsun->rx_time); 277a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 278a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); 279a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->rx_urb) 280a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 281a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 282a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); 283a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->tx_urb) 284a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 285a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 286a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* 287a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Now that everything should be initialized properly, 288a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * Open new IrLAP layer instance to take care of us... 289a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 290a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); 291a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); 292a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun->irlap) { 2936f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); 294a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 295a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 296a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 297a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Start first reception */ 298a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, 299a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), 300a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->in_buf, kingsun->max_rx, 301a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun_rcv_irq, kingsun, 1); 302a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb->status = 0; 303a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 304a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (err) { 3056f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&kingsun->usbdev->dev, 3066f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "first urb-submit failed: %d\n", 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 4239b634007d5694178c4e142fbc5f9dbcd767eafbdStephen Hemmingerstatic const struct net_device_ops kingsun_ops = { 4246518bbb803fe02b15a3211c8db2afdff0ac4f808Stephen Hemminger .ndo_start_xmit = kingsun_hard_xmit, 4259b634007d5694178c4e142fbc5f9dbcd767eafbdStephen Hemminger .ndo_open = kingsun_net_open, 4269b634007d5694178c4e142fbc5f9dbcd767eafbdStephen Hemminger .ndo_stop = kingsun_net_close, 4279b634007d5694178c4e142fbc5f9dbcd767eafbdStephen Hemminger .ndo_do_ioctl = kingsun_net_ioctl, 4289b634007d5694178c4e142fbc5f9dbcd767eafbdStephen Hemminger}; 429a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 430a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 431a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * This routine is called by the USB subsystem for each new device 432a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * in the system. We need to check if the device is ours, and in 433a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * this case start handling it. 434a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 435a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_probe(struct usb_interface *intf, 436a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso const struct usb_device_id *id) 437a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 438a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_host_interface *interface; 439a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_endpoint_descriptor *endpoint; 440a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 441a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct usb_device *dev = interface_to_usbdev(intf); 442a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = NULL; 443a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct net_device *net = NULL; 444a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int ret = -ENOMEM; 445a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso int pipe, maxp_in, maxp_out; 446a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_in; 447a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso __u8 ep_out; 448a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 449a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Check that there really are two interrupt endpoints. 450a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso Check based on the one in drivers/usb/input/usbmouse.c 451a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 452a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso interface = intf->cur_altsetting; 453a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (interface->desc.bNumEndpoints != 2) { 4546f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&intf->dev, 4556f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "kingsun-sir: expected 2 endpoints, found %d\n", 4566f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman interface->desc.bNumEndpoints); 457a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -ENODEV; 458a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 459a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; 460a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!usb_endpoint_is_int_in(endpoint)) { 4616f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&intf->dev, 4626f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "kingsun-sir: endpoint 0 is not interrupt IN\n"); 463a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -ENODEV; 464a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 465a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 466a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ep_in = endpoint->bEndpointAddress; 467a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso pipe = usb_rcvintpipe(dev, ep_in); 468a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 469a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (maxp_in > 255 || maxp_in <= 1) { 4706f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&intf->dev, 4716f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "endpoint 0 has max packet size %d not in range\n", 4726f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman 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)) { 4786f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman dev_err(&intf->dev, 4796f0d27ff97f66c041e2adc86b61e8957e8dd056dGreg Kroah-Hartman "kingsun-sir: endpoint 1 is not interrupt OUT\n"); 480a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return -ENODEV; 481a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 482a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 483a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ep_out = endpoint->bEndpointAddress; 484a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso pipe = usb_sndintpipe(dev, ep_out); 485a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 486a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 487a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Allocate network device container. */ 488a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso net = alloc_irdadev(sizeof(*kingsun)); 489a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if(!net) 490a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto err_out1; 491a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 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 */ 512901ded25fb98d76e55a8920834b173e7efc026b6Jesper Juhl kingsun->in_buf = 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 */ 517901ded25fb98d76e55a8920834b173e7efc026b6Jesper Juhl kingsun->out_buf = 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 */ 5359b634007d5694178c4e142fbc5f9dbcd767eafbdStephen Hemminger net->netdev_ops = &kingsun_ops; 536a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 537a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso ret = register_netdev(net); 538a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (ret != 0) 539a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso goto free_mem; 540a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 541880c9c66a60c0aa4fb4dac2da9679da5f8f41903Greg Kroah-Hartman dev_info(&net->dev, "IrDA: Registered KingSun/DonShine device %s\n", 542880c9c66a60c0aa4fb4dac2da9679da5f8f41903Greg Kroah-Hartman net->name); 543a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 544a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_set_intfdata(intf, kingsun); 545a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 546a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Situation at this point: 547a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - all work buffers allocated 548a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - urbs not allocated, set to NULL 549a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - max rx packet known (in max_rx) 550a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso - unwrap state machine (partially) initialized, but skb == NULL 551a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 552a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 553a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 554a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 555a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassofree_mem: 55644f71cef92eb65bc4382ef3fb04a8e1437bda2d7Fabian Frederick kfree(kingsun->out_buf); 55744f71cef92eb65bc4382ef3fb04a8e1437bda2d7Fabian Frederick kfree(kingsun->in_buf); 558a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso free_netdev(net); 559a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassoerr_out1: 560a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return ret; 561a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 562a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 563a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 564a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * The current device is removed, the USB layer tell us to shut it down... 565a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 566a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic void kingsun_disconnect(struct usb_interface *intf) 567a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 568a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = usb_get_intfdata(intf); 569a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 570a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (!kingsun) 571a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return; 572a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 573a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso unregister_netdev(kingsun->netdev); 574a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 575a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso /* Mop up receive && transmit urb's */ 576a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->tx_urb != NULL) { 577a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_kill_urb(kingsun->tx_urb); 578a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->tx_urb); 579a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->tx_urb = NULL; 580a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 581a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_urb != NULL) { 582a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_kill_urb(kingsun->rx_urb); 583a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_free_urb(kingsun->rx_urb); 584a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kingsun->rx_urb = NULL; 585a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso } 586a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 587a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kfree(kingsun->out_buf); 588a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso kfree(kingsun->in_buf); 589a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso free_netdev(kingsun->netdev); 590a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 591a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_set_intfdata(intf, NULL); 592a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 593a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 594a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#ifdef CONFIG_PM 595a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* USB suspend, so power off the transmitter/receiver */ 596a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_suspend(struct usb_interface *intf, pm_message_t message) 597a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 598a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = usb_get_intfdata(intf); 599a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 600a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_device_detach(kingsun->netdev); 601a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb); 602a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb); 603a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 604a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 605a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 606a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* Coming out of suspend, so reset hardware */ 607a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic int kingsun_resume(struct usb_interface *intf) 608a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso{ 609a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso struct kingsun_cb *kingsun = usb_get_intfdata(intf); 610a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 611a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso if (kingsun->rx_urb != NULL) 612a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); 613a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso netif_device_attach(kingsun->netdev); 614a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 615a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso return 0; 616a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso} 617a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#endif 618a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 619a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso/* 620a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso * USB device callbacks 621a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso */ 622a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lassostatic struct usb_driver irda_driver = { 623a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .name = "kingsun-sir", 624a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .probe = kingsun_probe, 625a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .disconnect = kingsun_disconnect, 626a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .id_table = dongles, 627a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#ifdef CONFIG_PM 628a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .suspend = kingsun_suspend, 629a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso .resume = kingsun_resume, 630a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso#endif 631a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso}; 632a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 633d632eb1bf22e11def74e4e53cc47d790fbdba105Greg Kroah-Hartmanmodule_usb_driver(irda_driver); 634a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s Lasso 63566f5e51ed5a300291b34bf3e2b1e22ac28ca3631Samuel OrtizMODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>"); 636a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s LassoMODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); 637a2af421f1819946556c6f467b1efdd0dc84af4d5Alex Villac�s LassoMODULE_LICENSE("GPL"); 638