linux/drivers/staging/vt6656/usbpipe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
   4 * All rights reserved.
   5 *
   6 * File: usbpipe.c
   7 *
   8 * Purpose: Handle USB control endpoint
   9 *
  10 * Author: Warren Hsu
  11 *
  12 * Date: Mar. 29, 2005
  13 *
  14 * Functions:
  15 *      vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
  16 *      vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
  17 *      vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
  18 *      vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
  19 *
  20 * Revision History:
  21 *      04-05-2004 Jerry Chen: Initial release
  22 *      11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,
  23 *                             ControlvMaskByte
  24 *
  25 */
  26
  27#include "int.h"
  28#include "rxtx.h"
  29#include "dpc.h"
  30#include "desc.h"
  31#include "device.h"
  32#include "usbpipe.h"
  33
  34#define USB_CTL_WAIT    500 /* ms */
  35
  36int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
  37                    u16 index, u16 length, u8 *buffer)
  38{
  39        int ret = 0;
  40        u8 *usb_buffer;
  41
  42        if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
  43                ret = -EINVAL;
  44                goto end;
  45        }
  46
  47        mutex_lock(&priv->usb_lock);
  48
  49        usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
  50        if (!usb_buffer) {
  51                ret = -ENOMEM;
  52                goto end_unlock;
  53        }
  54
  55        ret = usb_control_msg(priv->usb,
  56                              usb_sndctrlpipe(priv->usb, 0),
  57                              request, 0x40, value,
  58                              index, usb_buffer, length, USB_CTL_WAIT);
  59
  60        kfree(usb_buffer);
  61
  62        if (ret >= 0 && ret < (int)length)
  63                ret = -EIO;
  64
  65end_unlock:
  66        mutex_unlock(&priv->usb_lock);
  67end:
  68        return ret;
  69}
  70
  71int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
  72{
  73        return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
  74                               reg_off, reg, sizeof(u8), &data);
  75}
  76
  77int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
  78                   u16 index, u16 length, u8 *buffer)
  79{
  80        int ret = 0;
  81        u8 *usb_buffer;
  82
  83        if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
  84                ret = -EINVAL;
  85                goto end;
  86        }
  87
  88        mutex_lock(&priv->usb_lock);
  89
  90        usb_buffer = kmalloc(length, GFP_KERNEL);
  91        if (!usb_buffer) {
  92                ret = -ENOMEM;
  93                goto end_unlock;
  94        }
  95
  96        ret = usb_control_msg(priv->usb,
  97                              usb_rcvctrlpipe(priv->usb, 0),
  98                              request, 0xc0, value,
  99                              index, usb_buffer, length, USB_CTL_WAIT);
 100
 101        if (ret == length)
 102                memcpy(buffer, usb_buffer, length);
 103
 104        kfree(usb_buffer);
 105
 106        if (ret >= 0 && ret < (int)length)
 107                ret = -EIO;
 108
 109end_unlock:
 110        mutex_unlock(&priv->usb_lock);
 111end:
 112        return ret;
 113}
 114
 115int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
 116{
 117        return vnt_control_in(priv, MESSAGE_TYPE_READ,
 118                              reg_off, reg, sizeof(u8), data);
 119}
 120
 121static void vnt_start_interrupt_urb_complete(struct urb *urb)
 122{
 123        struct vnt_private *priv = urb->context;
 124        int status = urb->status;
 125
 126        switch (status) {
 127        case 0:
 128        case -ETIMEDOUT:
 129                break;
 130        case -ECONNRESET:
 131        case -ENOENT:
 132        case -ESHUTDOWN:
 133                priv->int_buf.in_use = false;
 134                return;
 135        default:
 136                break;
 137        }
 138
 139        if (status) {
 140                priv->int_buf.in_use = false;
 141
 142                dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
 143        } else {
 144                vnt_int_process_data(priv);
 145        }
 146
 147        status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
 148        if (status)
 149                dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
 150        else
 151                priv->int_buf.in_use = true;
 152}
 153
 154int vnt_start_interrupt_urb(struct vnt_private *priv)
 155{
 156        int ret = 0;
 157
 158        if (priv->int_buf.in_use) {
 159                ret = -EBUSY;
 160                goto err;
 161        }
 162
 163        priv->int_buf.in_use = true;
 164
 165        usb_fill_int_urb(priv->interrupt_urb,
 166                         priv->usb,
 167                         usb_rcvintpipe(priv->usb, 1),
 168                         priv->int_buf.data_buf,
 169                         MAX_INTERRUPT_SIZE,
 170                         vnt_start_interrupt_urb_complete,
 171                         priv,
 172                         priv->int_interval);
 173
 174        ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
 175        if (ret) {
 176                dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
 177                goto err_submit;
 178        }
 179
 180        return 0;
 181
 182err_submit:
 183        priv->int_buf.in_use = false;
 184err:
 185        return ret;
 186}
 187
 188static void vnt_submit_rx_urb_complete(struct urb *urb)
 189{
 190        struct vnt_rcb *rcb = urb->context;
 191        struct vnt_private *priv = rcb->priv;
 192
 193        switch (urb->status) {
 194        case 0:
 195                break;
 196        case -ECONNRESET:
 197        case -ENOENT:
 198        case -ESHUTDOWN:
 199                return;
 200        case -ETIMEDOUT:
 201        default:
 202                dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
 203                break;
 204        }
 205
 206        if (urb->actual_length) {
 207                if (vnt_rx_data(priv, rcb, urb->actual_length)) {
 208                        rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
 209                        if (!rcb->skb) {
 210                                rcb->in_use = false;
 211                                return;
 212                        }
 213                } else {
 214                        skb_push(rcb->skb, skb_headroom(rcb->skb));
 215                        skb_trim(rcb->skb, 0);
 216                }
 217
 218                urb->transfer_buffer = skb_put(rcb->skb,
 219                                                skb_tailroom(rcb->skb));
 220        }
 221
 222        if (usb_submit_urb(urb, GFP_ATOMIC)) {
 223                dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
 224
 225                rcb->in_use = false;
 226        }
 227}
 228
 229int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
 230{
 231        int ret = 0;
 232        struct urb *urb = rcb->urb;
 233
 234        if (!rcb->skb) {
 235                dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
 236                ret = -EINVAL;
 237                goto end;
 238        }
 239
 240        usb_fill_bulk_urb(urb,
 241                          priv->usb,
 242                          usb_rcvbulkpipe(priv->usb, 2),
 243                          skb_put(rcb->skb, skb_tailroom(rcb->skb)),
 244                          MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
 245                          vnt_submit_rx_urb_complete,
 246                          rcb);
 247
 248        ret = usb_submit_urb(urb, GFP_ATOMIC);
 249        if (ret) {
 250                dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
 251                goto end;
 252        }
 253
 254        rcb->in_use = true;
 255
 256end:
 257        return ret;
 258}
 259
 260static void vnt_tx_context_complete(struct urb *urb)
 261{
 262        struct vnt_usb_send_context *context = urb->context;
 263        struct vnt_private *priv = context->priv;
 264
 265        switch (urb->status) {
 266        case 0:
 267                dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
 268                break;
 269        case -ECONNRESET:
 270        case -ENOENT:
 271        case -ESHUTDOWN:
 272                context->in_use = false;
 273                return;
 274        case -ETIMEDOUT:
 275        default:
 276                dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
 277                break;
 278        }
 279
 280        if (context->type == CONTEXT_DATA_PACKET)
 281                ieee80211_wake_queues(priv->hw);
 282
 283        if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
 284                if (context->skb)
 285                        ieee80211_free_txskb(priv->hw, context->skb);
 286
 287                context->in_use = false;
 288        }
 289}
 290
 291int vnt_tx_context(struct vnt_private *priv,
 292                   struct vnt_usb_send_context *context)
 293{
 294        int status;
 295        struct urb *urb = context->urb;
 296
 297        if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 298                context->in_use = false;
 299                return STATUS_RESOURCES;
 300        }
 301
 302        usb_fill_bulk_urb(urb,
 303                          priv->usb,
 304                          usb_sndbulkpipe(priv->usb, 3),
 305                          context->data,
 306                          context->buf_len,
 307                          vnt_tx_context_complete,
 308                          context);
 309
 310        status = usb_submit_urb(urb, GFP_ATOMIC);
 311        if (status) {
 312                dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
 313
 314                context->in_use = false;
 315                return STATUS_FAILURE;
 316        }
 317
 318        return STATUS_PENDING;
 319}
 320