usbpipe.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. *
  20. * File: usbpipe.c
  21. *
  22. * Purpose: Handle USB control endpoint
  23. *
  24. * Author: Warren Hsu
  25. *
  26. * Date: Mar. 29, 2005
  27. *
  28. * Functions:
  29. * vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
  30. * vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
  31. * vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
  32. * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
  33. *
  34. * Revision History:
  35. * 04-05-2004 Jerry Chen: Initial release
  36. * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte
  37. *
  38. */
  39. #include "int.h"
  40. #include "rxtx.h"
  41. #include "dpc.h"
  42. #include "desc.h"
  43. #include "device.h"
  44. #include "usbpipe.h"
  45. #define USB_CTL_WAIT 500 /* ms */
  46. int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
  47. u16 index, u16 length, u8 *buffer)
  48. {
  49. int status = 0;
  50. if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
  51. return STATUS_FAILURE;
  52. mutex_lock(&priv->usb_lock);
  53. status = usb_control_msg(priv->usb,
  54. usb_sndctrlpipe(priv->usb, 0), request, 0x40, value,
  55. index, buffer, length, USB_CTL_WAIT);
  56. mutex_unlock(&priv->usb_lock);
  57. if (status < (int)length)
  58. return STATUS_FAILURE;
  59. return STATUS_SUCCESS;
  60. }
  61. void vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
  62. {
  63. vnt_control_out(priv, MESSAGE_TYPE_WRITE,
  64. reg_off, reg, sizeof(u8), &data);
  65. }
  66. int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
  67. u16 index, u16 length, u8 *buffer)
  68. {
  69. int status;
  70. if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
  71. return STATUS_FAILURE;
  72. mutex_lock(&priv->usb_lock);
  73. status = usb_control_msg(priv->usb,
  74. usb_rcvctrlpipe(priv->usb, 0), request, 0xc0, value,
  75. index, buffer, length, USB_CTL_WAIT);
  76. mutex_unlock(&priv->usb_lock);
  77. if (status < (int)length)
  78. return STATUS_FAILURE;
  79. return STATUS_SUCCESS;
  80. }
  81. void vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
  82. {
  83. vnt_control_in(priv, MESSAGE_TYPE_READ,
  84. reg_off, reg, sizeof(u8), data);
  85. }
  86. static void vnt_start_interrupt_urb_complete(struct urb *urb)
  87. {
  88. struct vnt_private *priv = urb->context;
  89. int status;
  90. switch (urb->status) {
  91. case 0:
  92. case -ETIMEDOUT:
  93. break;
  94. case -ECONNRESET:
  95. case -ENOENT:
  96. case -ESHUTDOWN:
  97. priv->int_buf.in_use = false;
  98. return;
  99. default:
  100. break;
  101. }
  102. status = urb->status;
  103. if (status != STATUS_SUCCESS) {
  104. priv->int_buf.in_use = false;
  105. dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
  106. } else {
  107. vnt_int_process_data(priv);
  108. }
  109. status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
  110. if (status)
  111. dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
  112. else
  113. priv->int_buf.in_use = true;
  114. }
  115. int vnt_start_interrupt_urb(struct vnt_private *priv)
  116. {
  117. int status = STATUS_FAILURE;
  118. if (priv->int_buf.in_use == true)
  119. return STATUS_FAILURE;
  120. priv->int_buf.in_use = true;
  121. usb_fill_int_urb(priv->interrupt_urb,
  122. priv->usb,
  123. usb_rcvintpipe(priv->usb, 1),
  124. priv->int_buf.data_buf,
  125. MAX_INTERRUPT_SIZE,
  126. vnt_start_interrupt_urb_complete,
  127. priv,
  128. priv->int_interval);
  129. status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
  130. if (status) {
  131. dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
  132. priv->int_buf.in_use = false;
  133. }
  134. return status;
  135. }
  136. static void vnt_submit_rx_urb_complete(struct urb *urb)
  137. {
  138. struct vnt_rcb *rcb = urb->context;
  139. struct vnt_private *priv = rcb->priv;
  140. unsigned long flags;
  141. switch (urb->status) {
  142. case 0:
  143. break;
  144. case -ECONNRESET:
  145. case -ENOENT:
  146. case -ESHUTDOWN:
  147. return;
  148. case -ETIMEDOUT:
  149. default:
  150. dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
  151. break;
  152. }
  153. if (urb->actual_length) {
  154. spin_lock_irqsave(&priv->lock, flags);
  155. if (vnt_rx_data(priv, rcb, urb->actual_length)) {
  156. rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
  157. if (!rcb->skb) {
  158. dev_dbg(&priv->usb->dev,
  159. "Failed to re-alloc rx skb\n");
  160. rcb->in_use = false;
  161. spin_unlock_irqrestore(&priv->lock, flags);
  162. return;
  163. }
  164. } else {
  165. skb_push(rcb->skb, skb_headroom(rcb->skb));
  166. skb_trim(rcb->skb, 0);
  167. }
  168. urb->transfer_buffer = skb_put(rcb->skb,
  169. skb_tailroom(rcb->skb));
  170. spin_unlock_irqrestore(&priv->lock, flags);
  171. }
  172. if (usb_submit_urb(urb, GFP_ATOMIC)) {
  173. dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
  174. rcb->in_use = false;
  175. }
  176. }
  177. int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
  178. {
  179. int status = 0;
  180. struct urb *urb;
  181. urb = rcb->urb;
  182. if (rcb->skb == NULL) {
  183. dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
  184. return status;
  185. }
  186. usb_fill_bulk_urb(urb,
  187. priv->usb,
  188. usb_rcvbulkpipe(priv->usb, 2),
  189. skb_put(rcb->skb, skb_tailroom(rcb->skb)),
  190. MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
  191. vnt_submit_rx_urb_complete,
  192. rcb);
  193. status = usb_submit_urb(urb, GFP_ATOMIC);
  194. if (status != 0) {
  195. dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", status);
  196. return STATUS_FAILURE;
  197. }
  198. rcb->in_use = true;
  199. return status;
  200. }
  201. static void vnt_tx_context_complete(struct urb *urb)
  202. {
  203. struct vnt_usb_send_context *context = urb->context;
  204. struct vnt_private *priv = context->priv;
  205. switch (urb->status) {
  206. case 0:
  207. dev_dbg(&priv->usb->dev, "Write %d bytes\n", context->buf_len);
  208. break;
  209. case -ECONNRESET:
  210. case -ENOENT:
  211. case -ESHUTDOWN:
  212. context->in_use = false;
  213. return;
  214. case -ETIMEDOUT:
  215. default:
  216. dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
  217. break;
  218. }
  219. if (context->type == CONTEXT_DATA_PACKET)
  220. ieee80211_wake_queues(priv->hw);
  221. if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
  222. if (context->skb)
  223. ieee80211_free_txskb(priv->hw, context->skb);
  224. context->in_use = false;
  225. }
  226. }
  227. int vnt_tx_context(struct vnt_private *priv,
  228. struct vnt_usb_send_context *context)
  229. {
  230. int status;
  231. struct urb *urb;
  232. if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
  233. context->in_use = false;
  234. return STATUS_RESOURCES;
  235. }
  236. urb = context->urb;
  237. usb_fill_bulk_urb(urb,
  238. priv->usb,
  239. usb_sndbulkpipe(priv->usb, 3),
  240. context->data,
  241. context->buf_len,
  242. vnt_tx_context_complete,
  243. context);
  244. status = usb_submit_urb(urb, GFP_ATOMIC);
  245. if (status != 0) {
  246. dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
  247. context->in_use = false;
  248. return STATUS_FAILURE;
  249. }
  250. return STATUS_PENDING;
  251. }