/******************************************************************************
*
* Copyright(c) 2009-2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
*****************************************************************************/
#include <linux/usb.h>
#include "core.h"
#include "wifi.h"
#include "usb.h"
#include "base.h"
#include "ps.h"
#define REALTEK_USB_VENQT_READ 0xC0
#define REALTEK_USB_VENQT_WRITE 0x40
#define REALTEK_USB_VENQT_CMD_REQ 0x05
#define REALTEK_USB_VENQT_CMD_IDX 0x00
#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254
static void usbctrl_async_callback(struct urb *urb)
{
if (urb)
kfree(urb->context);
}
static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
u16 value, u16 index, void *pdata,
u16 len)
{
int rc;
unsigned int pipe;
u8 reqtype;
struct usb_ctrlrequest *dr;
struct urb *urb;
struct rtl819x_async_write_data {
u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE];
struct usb_ctrlrequest dr;
} *buf;
pipe = usb_sndctrlpipe(udev, 0); /* write_out */
reqtype = REALTEK_USB_VENQT_WRITE;
buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
if (!buf)
return -ENOMEM;
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
kfree(buf);
return -ENOMEM;
}
dr = &buf->dr;
dr->bRequestType = reqtype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(len);
memcpy(buf, pdata, len);
usb_fill_control_urb(urb, udev, pipe,
(unsigned char *)dr, buf, len,
usbctrl_async_callback, buf);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0)
kfree(buf);
usb_free_urb(urb);
return rc;
}
static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
u16 value, u16 index, void *pdata,
u16 len)
{
unsigned int pipe;
int status;
u8 reqtype;
pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
reqtype = REALTEK_USB_VENQT_READ;
status = usb_control_msg(udev, pipe, request, reqtype, value, index,
pdata, len, 0); /* max. timeout */
if (status < 0)
printk(KERN_ERR "reg 0x%x, usbctrl_vendorreq TimeOut! "
"status:0x%x value=0x%x\n", value, status,
*(u32 *)pdata);
return status;
}
static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
{
u8 request;
u16 wvalue;
u16 index;
u32 *data;
u32 ret;
data = kmalloc(sizeof(u32), GFP_KERNEL);
if (!data)
return -ENOMEM;
request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
wvalue = (u16)addr;
_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
ret = *data;
kfree(data);
return ret;
}
static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
struct device *dev = rtlpriv->io.dev;
return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
}
static u16 _usb_read16_sync(struct rtl_priv *rtlpriv,