// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009-2012 Realtek Corporation.*/
#include "wifi.h"
#include "core.h"
#include "usb.h"
#include "base.h"
#include "ps.h"
#include "rtl8192c/fw_common.h"
#include <linux/export.h>
#include <linux/module.h>
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("USB basic driver for rtlwifi");
#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 MAX_USBCTRL_VENDORREQ_TIMES 10
static void usbctrl_async_callback(struct urb *urb)
{
if (urb) {
/* free dr */
kfree(urb->setup_packet);
/* free databuf */
kfree(urb->transfer_buffer);
}
}
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;
const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE;
u8 *databuf;
if (WARN_ON_ONCE(len > databuf_maxlen))
len = databuf_maxlen;
pipe = usb_sndctrlpipe(udev, 0); /* write_out */
reqtype = REALTEK_USB_VENQT_WRITE;
dr = kzalloc(sizeof(*dr), GFP_ATOMIC);
if (!dr)
return -ENOMEM;
databuf = kzalloc(databuf_maxlen, GFP_ATOMIC);
if (!databuf) {
kfree(dr);
return -ENOMEM;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
kfree(databuf);
kfree(dr);
return -ENOMEM;
}
dr->bRequestType = reqtype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(len);
/* data are already in little-endian order */
memcpy(databuf, pdata, len);
usb_fill_control_urb(urb, udev, pipe,
(unsigned char *)dr, databuf, len,
usbctrl_async_callback, NULL);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0) {
kfree(databuf);
kfree(dr);
}
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;
int vendorreq_times = 0;
static int count;
pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
reqtype = REALTEK_USB_VENQT_READ;
do {
status = usb_control_msg(udev, pipe, request, reqtype, value,
index, pdata, len, 1000);
if (status < 0) {
/* firmware download is checksumed, don't retry */
if ((value >= FW_8192C_START_ADDRESS &&
value <= FW_8192C_END_ADDRESS)