aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2012-08-13 07:59:39 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-13 15:04:18 -0400
commite99a7cfe93fd9b853d80e7dda8b86ecca71c22bb (patch)
treecd44d461c423bd4a4ef2af7044e64d64f5dd3264 /drivers/media
parentc6afbf298bde96209099c3b9aaf35c5937789a75 (diff)
[media] iguanair: reuse existing urb callback for command responses
Rather than using usb_interrupt_msg() to receive responses, reuse the urb callback we already have in place. Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/rc/iguanair.c147
1 files changed, 56 insertions, 91 deletions
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 5e2eaf8ba73e..bdd526df0b74 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -35,7 +35,7 @@ struct iguanair {
35 struct device *dev; 35 struct device *dev;
36 struct usb_device *udev; 36 struct usb_device *udev;
37 37
38 int pipe_in, pipe_out; 38 int pipe_out;
39 uint8_t bufsize; 39 uint8_t bufsize;
40 uint8_t version[2]; 40 uint8_t version[2];
41 41
@@ -82,11 +82,6 @@ struct packet {
82 uint8_t cmd; 82 uint8_t cmd;
83}; 83};
84 84
85struct response_packet {
86 struct packet header;
87 uint8_t data[4];
88};
89
90struct send_packet { 85struct send_packet {
91 struct packet header; 86 struct packet header;
92 uint8_t length; 87 uint8_t length;
@@ -100,6 +95,26 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
100{ 95{
101 if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) { 96 if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) {
102 switch (ir->buf_in[3]) { 97 switch (ir->buf_in[3]) {
98 case CMD_GET_VERSION:
99 if (len == 6) {
100 ir->version[0] = ir->buf_in[4];
101 ir->version[1] = ir->buf_in[5];
102 complete(&ir->completion);
103 }
104 break;
105 case CMD_GET_BUFSIZE:
106 if (len >= 5) {
107 ir->bufsize = ir->buf_in[4];
108 complete(&ir->completion);
109 }
110 break;
111 case CMD_GET_FEATURES:
112 if (len > 5) {
113 if (ir->version[0] >= 4)
114 ir->cycle_overhead = ir->buf_in[5];
115 complete(&ir->completion);
116 }
117 break;
103 case CMD_TX_OVERFLOW: 118 case CMD_TX_OVERFLOW:
104 ir->tx_overflow = true; 119 ir->tx_overflow = true;
105 case CMD_RECEIVER_OFF: 120 case CMD_RECEIVER_OFF:
@@ -169,31 +184,22 @@ static void iguanair_rx(struct urb *urb)
169 usb_submit_urb(urb, GFP_ATOMIC); 184 usb_submit_urb(urb, GFP_ATOMIC);
170} 185}
171 186
172static int iguanair_send(struct iguanair *ir, void *data, unsigned size, 187static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
173 struct response_packet *response, unsigned *res_len)
174{ 188{
175 unsigned offset, len;
176 int rc, transferred; 189 int rc, transferred;
177 190
178 for (offset = 0; offset < size; offset += MAX_PACKET_SIZE) { 191 INIT_COMPLETION(ir->completion);
179 len = min(size - offset, MAX_PACKET_SIZE);
180
181 if (ir->tx_overflow)
182 return -EOVERFLOW;
183 192
184 rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data + offset, 193 rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size,
185 len, &transferred, TIMEOUT); 194 &transferred, TIMEOUT);
186 if (rc) 195 if (rc)
187 return rc; 196 return rc;
188 197
189 if (transferred != len) 198 if (transferred != size)
190 return -EIO; 199 return -EIO;
191 }
192 200
193 if (response) { 201 if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
194 rc = usb_interrupt_msg(ir->udev, ir->pipe_in, response, 202 return -ETIMEDOUT;
195 sizeof(*response), res_len, TIMEOUT);
196 }
197 203
198 return rc; 204 return rc;
199} 205}
@@ -201,66 +207,40 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size,
201static int iguanair_get_features(struct iguanair *ir) 207static int iguanair_get_features(struct iguanair *ir)
202{ 208{
203 struct packet packet; 209 struct packet packet;
204 struct response_packet response; 210 int rc;
205 int rc, len;
206 211
207 packet.start = 0; 212 packet.start = 0;
208 packet.direction = DIR_OUT; 213 packet.direction = DIR_OUT;
209 packet.cmd = CMD_GET_VERSION; 214 packet.cmd = CMD_GET_VERSION;
210 215
211 rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); 216 rc = iguanair_send(ir, &packet, sizeof(packet));
212 if (rc) { 217 if (rc) {
213 dev_info(ir->dev, "failed to get version\n"); 218 dev_info(ir->dev, "failed to get version\n");
214 goto out; 219 goto out;
215 } 220 }
216 221
217 if (len != 6) {
218 dev_info(ir->dev, "failed to get version\n");
219 rc = -EIO;
220 goto out;
221 }
222
223 ir->version[0] = response.data[0];
224 ir->version[1] = response.data[1];
225 ir->bufsize = 150; 222 ir->bufsize = 150;
226 ir->cycle_overhead = 65; 223 ir->cycle_overhead = 65;
227 224
228 packet.cmd = CMD_GET_BUFSIZE; 225 packet.cmd = CMD_GET_BUFSIZE;
229 226
230 rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); 227 rc = iguanair_send(ir, &packet, sizeof(packet));
231 if (rc) { 228 if (rc) {
232 dev_info(ir->dev, "failed to get buffer size\n"); 229 dev_info(ir->dev, "failed to get buffer size\n");
233 goto out; 230 goto out;
234 } 231 }
235 232
236 if (len != 5) {
237 dev_info(ir->dev, "failed to get buffer size\n");
238 rc = -EIO;
239 goto out;
240 }
241
242 ir->bufsize = response.data[0];
243
244 if (ir->version[0] == 0 || ir->version[1] == 0) 233 if (ir->version[0] == 0 || ir->version[1] == 0)
245 goto out; 234 goto out;
246 235
247 packet.cmd = CMD_GET_FEATURES; 236 packet.cmd = CMD_GET_FEATURES;
248 237
249 rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len); 238 rc = iguanair_send(ir, &packet, sizeof(packet));
250 if (rc) { 239 if (rc) {
251 dev_info(ir->dev, "failed to get features\n"); 240 dev_info(ir->dev, "failed to get features\n");
252 goto out; 241 goto out;
253 } 242 }
254 243
255 if (len < 5) {
256 dev_info(ir->dev, "failed to get features\n");
257 rc = -EIO;
258 goto out;
259 }
260
261 if (len > 5 && ir->version[0] >= 4)
262 ir->cycle_overhead = response.data[1];
263
264out: 244out:
265 return rc; 245 return rc;
266} 246}
@@ -269,17 +249,8 @@ static int iguanair_receiver(struct iguanair *ir, bool enable)
269{ 249{
270 struct packet packet = { 0, DIR_OUT, enable ? 250 struct packet packet = { 0, DIR_OUT, enable ?
271 CMD_RECEIVER_ON : CMD_RECEIVER_OFF }; 251 CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
272 int rc;
273
274 INIT_COMPLETION(ir->completion);
275
276 rc = iguanair_send(ir, &packet, sizeof(packet), NULL, NULL);
277 if (rc)
278 return rc;
279
280 wait_for_completion_timeout(&ir->completion, TIMEOUT);
281 252
282 return 0; 253 return iguanair_send(ir, &packet, sizeof(packet));
283} 254}
284 255
285/* 256/*
@@ -406,17 +377,10 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
406 377
407 ir->tx_overflow = false; 378 ir->tx_overflow = false;
408 379
409 INIT_COMPLETION(ir->completion); 380 rc = iguanair_send(ir, packet, size + 8);
410
411 rc = iguanair_send(ir, packet, size + 8, NULL, NULL);
412 381
413 if (rc == 0) { 382 if (rc == 0 && ir->tx_overflow)
414 wait_for_completion_timeout(&ir->completion, TIMEOUT); 383 rc = -EOVERFLOW;
415 if (ir->tx_overflow)
416 rc = -EOVERFLOW;
417 }
418
419 ir->tx_overflow = false;
420 384
421 if (ir->receiver_on) { 385 if (ir->receiver_on) {
422 if (iguanair_receiver(ir, true)) 386 if (iguanair_receiver(ir, true))
@@ -437,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev)
437 401
438 mutex_lock(&ir->lock); 402 mutex_lock(&ir->lock);
439 403
440 usb_submit_urb(ir->urb_in, GFP_KERNEL);
441
442 BUG_ON(ir->receiver_on); 404 BUG_ON(ir->receiver_on);
443 405
444 rc = iguanair_receiver(ir, true); 406 rc = iguanair_receiver(ir, true);
@@ -462,8 +424,6 @@ static void iguanair_close(struct rc_dev *rdev)
462 if (rc) 424 if (rc)
463 dev_warn(ir->dev, "failed to disable receiver: %d\n", rc); 425 dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
464 426
465 usb_kill_urb(ir->urb_in);
466
467 mutex_unlock(&ir->lock); 427 mutex_unlock(&ir->lock);
468} 428}
469 429
@@ -473,7 +433,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
473 struct usb_device *udev = interface_to_usbdev(intf); 433 struct usb_device *udev = interface_to_usbdev(intf);
474 struct iguanair *ir; 434 struct iguanair *ir;
475 struct rc_dev *rc; 435 struct rc_dev *rc;
476 int ret; 436 int ret, pipein;
477 struct usb_host_interface *idesc; 437 struct usb_host_interface *idesc;
478 438
479 ir = kzalloc(sizeof(*ir), GFP_KERNEL); 439 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
@@ -483,7 +443,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
483 goto out; 443 goto out;
484 } 444 }
485 445
486 ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_ATOMIC, 446 ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL,
487 &ir->dma_in); 447 &ir->dma_in);
488 ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); 448 ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
489 449
@@ -502,25 +462,28 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
502 ir->rc = rc; 462 ir->rc = rc;
503 ir->dev = &intf->dev; 463 ir->dev = &intf->dev;
504 ir->udev = udev; 464 ir->udev = udev;
505 ir->pipe_in = usb_rcvintpipe(udev,
506 idesc->endpoint[0].desc.bEndpointAddress);
507 ir->pipe_out = usb_sndintpipe(udev, 465 ir->pipe_out = usb_sndintpipe(udev,
508 idesc->endpoint[1].desc.bEndpointAddress); 466 idesc->endpoint[1].desc.bEndpointAddress);
509 mutex_init(&ir->lock); 467 mutex_init(&ir->lock);
510 init_completion(&ir->completion); 468 init_completion(&ir->completion);
511 469
512 ret = iguanair_get_features(ir); 470 pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
513 if (ret) { 471 usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in,
514 dev_warn(&intf->dev, "failed to get device features");
515 goto out;
516 }
517
518 usb_fill_int_urb(ir->urb_in, ir->udev, ir->pipe_in, ir->buf_in,
519 MAX_PACKET_SIZE, iguanair_rx, ir, 472 MAX_PACKET_SIZE, iguanair_rx, ir,
520 idesc->endpoint[0].desc.bInterval); 473 idesc->endpoint[0].desc.bInterval);
521 ir->urb_in->transfer_dma = ir->dma_in; 474 ir->urb_in->transfer_dma = ir->dma_in;
522 ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 475 ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
523 476
477 ret = usb_submit_urb(ir->urb_in, GFP_KERNEL);
478 if (ret) {
479 dev_warn(&intf->dev, "failed to submit urb: %d\n", ret);
480 goto out;
481 }
482
483 ret = iguanair_get_features(ir);
484 if (ret)
485 goto out2;
486
524 snprintf(ir->name, sizeof(ir->name), 487 snprintf(ir->name, sizeof(ir->name),
525 "IguanaWorks USB IR Transceiver version %d.%d", 488 "IguanaWorks USB IR Transceiver version %d.%d",
526 ir->version[0], ir->version[1]); 489 ir->version[0], ir->version[1]);
@@ -547,7 +510,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
547 ret = rc_register_device(rc); 510 ret = rc_register_device(rc);
548 if (ret < 0) { 511 if (ret < 0) {
549 dev_err(&intf->dev, "failed to register rc device %d", ret); 512 dev_err(&intf->dev, "failed to register rc device %d", ret);
550 goto out; 513 goto out2;
551 } 514 }
552 515
553 usb_set_intfdata(intf, ir); 516 usb_set_intfdata(intf, ir);
@@ -555,6 +518,8 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
555 dev_info(&intf->dev, "Registered %s", ir->name); 518 dev_info(&intf->dev, "Registered %s", ir->name);
556 519
557 return 0; 520 return 0;
521out2:
522 usb_kill_urb(ir->urb_in);
558out: 523out:
559 if (ir) { 524 if (ir) {
560 usb_free_urb(ir->urb_in); 525 usb_free_urb(ir->urb_in);