usbpipe.c 6.9 KB

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