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