root/drivers/staging/vt6656/usbpipe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vnt_control_out
  2. vnt_control_out_u8
  3. vnt_control_out_blocks
  4. vnt_control_in
  5. vnt_control_in_u8
  6. vnt_start_interrupt_urb_complete
  7. vnt_start_interrupt_urb
  8. vnt_submit_rx_urb_complete
  9. vnt_submit_rx_urb
  10. vnt_tx_context_complete
  11. vnt_tx_context

   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 
  36 int 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 == (int)length)
  63                 ret = 0;
  64         else
  65                 ret = -EIO;
  66 
  67 end_unlock:
  68         mutex_unlock(&priv->usb_lock);
  69 end:
  70         return ret;
  71 }
  72 
  73 int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
  74 {
  75         return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
  76                                reg_off, reg, sizeof(u8), &data);
  77 }
  78 
  79 int vnt_control_out_blocks(struct vnt_private *priv,
  80                            u16 block, u8 reg, u16 length, u8 *data)
  81 {
  82         int ret = 0, i;
  83 
  84         for (i = 0; i < length; i += block) {
  85                 u16 len = min_t(int, length - i, block);
  86 
  87                 ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE,
  88                                       i, reg, len, data + i);
  89                 if (ret)
  90                         goto end;
  91         }
  92 end:
  93         return ret;
  94 }
  95 
  96 int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
  97                    u16 index, u16 length, u8 *buffer)
  98 {
  99         int ret = 0;
 100         u8 *usb_buffer;
 101 
 102         if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 103                 ret = -EINVAL;
 104                 goto end;
 105         }
 106 
 107         mutex_lock(&priv->usb_lock);
 108 
 109         usb_buffer = kmalloc(length, GFP_KERNEL);
 110         if (!usb_buffer) {
 111                 ret = -ENOMEM;
 112                 goto end_unlock;
 113         }
 114 
 115         ret = usb_control_msg(priv->usb,
 116                               usb_rcvctrlpipe(priv->usb, 0),
 117                               request, 0xc0, value,
 118                               index, usb_buffer, length, USB_CTL_WAIT);
 119 
 120         if (ret == length)
 121                 memcpy(buffer, usb_buffer, length);
 122 
 123         kfree(usb_buffer);
 124 
 125         if (ret == (int)length)
 126                 ret = 0;
 127         else
 128                 ret = -EIO;
 129 
 130 end_unlock:
 131         mutex_unlock(&priv->usb_lock);
 132 end:
 133         return ret;
 134 }
 135 
 136 int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
 137 {
 138         return vnt_control_in(priv, MESSAGE_TYPE_READ,
 139                               reg_off, reg, sizeof(u8), data);
 140 }
 141 
 142 static void vnt_start_interrupt_urb_complete(struct urb *urb)
 143 {
 144         struct vnt_private *priv = urb->context;
 145         int status = urb->status;
 146 
 147         switch (status) {
 148         case 0:
 149         case -ETIMEDOUT:
 150                 break;
 151         case -ECONNRESET:
 152         case -ENOENT:
 153         case -ESHUTDOWN:
 154                 priv->int_buf.in_use = false;
 155                 return;
 156         default:
 157                 break;
 158         }
 159 
 160         if (status) {
 161                 priv->int_buf.in_use = false;
 162 
 163                 dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
 164         } else {
 165                 vnt_int_process_data(priv);
 166         }
 167 
 168         status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
 169         if (status)
 170                 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
 171         else
 172                 priv->int_buf.in_use = true;
 173 }
 174 
 175 int vnt_start_interrupt_urb(struct vnt_private *priv)
 176 {
 177         int ret = 0;
 178 
 179         if (priv->int_buf.in_use) {
 180                 ret = -EBUSY;
 181                 goto err;
 182         }
 183 
 184         priv->int_buf.in_use = true;
 185 
 186         usb_fill_int_urb(priv->interrupt_urb,
 187                          priv->usb,
 188                          usb_rcvintpipe(priv->usb, 1),
 189                          priv->int_buf.data_buf,
 190                          MAX_INTERRUPT_SIZE,
 191                          vnt_start_interrupt_urb_complete,
 192                          priv,
 193                          priv->int_interval);
 194 
 195         ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
 196         if (ret) {
 197                 dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
 198                 goto err_submit;
 199         }
 200 
 201         return 0;
 202 
 203 err_submit:
 204         priv->int_buf.in_use = false;
 205 err:
 206         return ret;
 207 }
 208 
 209 static void vnt_submit_rx_urb_complete(struct urb *urb)
 210 {
 211         struct vnt_rcb *rcb = urb->context;
 212         struct vnt_private *priv = rcb->priv;
 213 
 214         switch (urb->status) {
 215         case 0:
 216                 break;
 217         case -ECONNRESET:
 218         case -ENOENT:
 219         case -ESHUTDOWN:
 220                 return;
 221         case -ETIMEDOUT:
 222         default:
 223                 dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
 224                 break;
 225         }
 226 
 227         if (urb->actual_length) {
 228                 if (vnt_rx_data(priv, rcb, urb->actual_length)) {
 229                         rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
 230                         if (!rcb->skb) {
 231                                 rcb->in_use = false;
 232                                 return;
 233                         }
 234                 } else {
 235                         skb_push(rcb->skb, skb_headroom(rcb->skb));
 236                         skb_trim(rcb->skb, 0);
 237                 }
 238 
 239                 urb->transfer_buffer = skb_put(rcb->skb,
 240                                                skb_tailroom(rcb->skb));
 241         }
 242 
 243         if (usb_submit_urb(urb, GFP_ATOMIC)) {
 244                 dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
 245 
 246                 rcb->in_use = false;
 247         }
 248 }
 249 
 250 int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
 251 {
 252         int ret = 0;
 253         struct urb *urb = rcb->urb;
 254 
 255         if (!rcb->skb) {
 256                 dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
 257                 ret = -EINVAL;
 258                 goto end;
 259         }
 260 
 261         usb_fill_bulk_urb(urb,
 262                           priv->usb,
 263                           usb_rcvbulkpipe(priv->usb, 2),
 264                           skb_put(rcb->skb, skb_tailroom(rcb->skb)),
 265                           MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
 266                           vnt_submit_rx_urb_complete,
 267                           rcb);
 268 
 269         ret = usb_submit_urb(urb, GFP_ATOMIC);
 270         if (ret) {
 271                 dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
 272                 goto end;
 273         }
 274 
 275         rcb->in_use = true;
 276 
 277 end:
 278         return ret;
 279 }
 280 
 281 static void vnt_tx_context_complete(struct urb *urb)
 282 {
 283         struct vnt_usb_send_context *context = urb->context;
 284         struct vnt_private *priv = context->priv;
 285 
 286         switch (urb->status) {
 287         case 0:
 288                 dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
 289                 break;
 290         case -ECONNRESET:
 291         case -ENOENT:
 292         case -ESHUTDOWN:
 293                 context->in_use = false;
 294                 return;
 295         case -ETIMEDOUT:
 296         default:
 297                 dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
 298                 break;
 299         }
 300 
 301         if (context->type == CONTEXT_DATA_PACKET)
 302                 ieee80211_wake_queues(priv->hw);
 303 
 304         if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
 305                 if (context->skb)
 306                         ieee80211_free_txskb(priv->hw, context->skb);
 307 
 308                 context->in_use = false;
 309         }
 310 }
 311 
 312 int vnt_tx_context(struct vnt_private *priv,
 313                    struct vnt_usb_send_context *context)
 314 {
 315         int status;
 316         struct urb *urb = context->urb;
 317 
 318         if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 319                 context->in_use = false;
 320                 return STATUS_RESOURCES;
 321         }
 322 
 323         usb_fill_bulk_urb(urb,
 324                           priv->usb,
 325                           usb_sndbulkpipe(priv->usb, 3),
 326                           context->data,
 327                           context->buf_len,
 328                           vnt_tx_context_complete,
 329                           context);
 330 
 331         status = usb_submit_urb(urb, GFP_ATOMIC);
 332         if (status) {
 333                 dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
 334 
 335                 context->in_use = false;
 336                 return STATUS_FAILURE;
 337         }
 338 
 339         return STATUS_PENDING;
 340 }

/* [<][>][^][v][top][bottom][index][help] */