usbpipe.c 7.2 KB

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