Skip to content

Commit e99a7cf

Browse files
seanyoungMauro Carvalho Chehab
authored andcommitted
[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 <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent c6afbf2 commit e99a7cf

File tree

1 file changed

+56
-91
lines changed

1 file changed

+56
-91
lines changed

drivers/media/rc/iguanair.c

Lines changed: 56 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct iguanair {
3535
struct device *dev;
3636
struct usb_device *udev;
3737

38-
int pipe_in, pipe_out;
38+
int pipe_out;
3939
uint8_t bufsize;
4040
uint8_t version[2];
4141

@@ -82,11 +82,6 @@ struct packet {
8282
uint8_t cmd;
8383
};
8484

85-
struct response_packet {
86-
struct packet header;
87-
uint8_t data[4];
88-
};
89-
9085
struct send_packet {
9186
struct packet header;
9287
uint8_t length;
@@ -100,6 +95,26 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
10095
{
10196
if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) {
10297
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;
103118
case CMD_TX_OVERFLOW:
104119
ir->tx_overflow = true;
105120
case CMD_RECEIVER_OFF:
@@ -169,98 +184,63 @@ static void iguanair_rx(struct urb *urb)
169184
usb_submit_urb(urb, GFP_ATOMIC);
170185
}
171186

172-
static int iguanair_send(struct iguanair *ir, void *data, unsigned size,
173-
struct response_packet *response, unsigned *res_len)
187+
static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
174188
{
175-
unsigned offset, len;
176189
int rc, transferred;
177190

178-
for (offset = 0; offset < size; offset += MAX_PACKET_SIZE) {
179-
len = min(size - offset, MAX_PACKET_SIZE);
180-
181-
if (ir->tx_overflow)
182-
return -EOVERFLOW;
191+
INIT_COMPLETION(ir->completion);
183192

184-
rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data + offset,
185-
len, &transferred, TIMEOUT);
186-
if (rc)
187-
return rc;
193+
rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size,
194+
&transferred, TIMEOUT);
195+
if (rc)
196+
return rc;
188197

189-
if (transferred != len)
190-
return -EIO;
191-
}
198+
if (transferred != size)
199+
return -EIO;
192200

193-
if (response) {
194-
rc = usb_interrupt_msg(ir->udev, ir->pipe_in, response,
195-
sizeof(*response), res_len, TIMEOUT);
196-
}
201+
if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
202+
return -ETIMEDOUT;
197203

198204
return rc;
199205
}
200206

201207
static int iguanair_get_features(struct iguanair *ir)
202208
{
203209
struct packet packet;
204-
struct response_packet response;
205-
int rc, len;
210+
int rc;
206211

207212
packet.start = 0;
208213
packet.direction = DIR_OUT;
209214
packet.cmd = CMD_GET_VERSION;
210215

211-
rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
216+
rc = iguanair_send(ir, &packet, sizeof(packet));
212217
if (rc) {
213218
dev_info(ir->dev, "failed to get version\n");
214219
goto out;
215220
}
216221

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];
225222
ir->bufsize = 150;
226223
ir->cycle_overhead = 65;
227224

228225
packet.cmd = CMD_GET_BUFSIZE;
229226

230-
rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
227+
rc = iguanair_send(ir, &packet, sizeof(packet));
231228
if (rc) {
232229
dev_info(ir->dev, "failed to get buffer size\n");
233230
goto out;
234231
}
235232

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-
244233
if (ir->version[0] == 0 || ir->version[1] == 0)
245234
goto out;
246235

247236
packet.cmd = CMD_GET_FEATURES;
248237

249-
rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
238+
rc = iguanair_send(ir, &packet, sizeof(packet));
250239
if (rc) {
251240
dev_info(ir->dev, "failed to get features\n");
252241
goto out;
253242
}
254243

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-
264244
out:
265245
return rc;
266246
}
@@ -269,17 +249,8 @@ static int iguanair_receiver(struct iguanair *ir, bool enable)
269249
{
270250
struct packet packet = { 0, DIR_OUT, enable ?
271251
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);
281252

282-
return 0;
253+
return iguanair_send(ir, &packet, sizeof(packet));
283254
}
284255

285256
/*
@@ -406,17 +377,10 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
406377

407378
ir->tx_overflow = false;
408379

409-
INIT_COMPLETION(ir->completion);
410-
411-
rc = iguanair_send(ir, packet, size + 8, NULL, NULL);
380+
rc = iguanair_send(ir, packet, size + 8);
412381

413-
if (rc == 0) {
414-
wait_for_completion_timeout(&ir->completion, TIMEOUT);
415-
if (ir->tx_overflow)
416-
rc = -EOVERFLOW;
417-
}
418-
419-
ir->tx_overflow = false;
382+
if (rc == 0 && ir->tx_overflow)
383+
rc = -EOVERFLOW;
420384

421385
if (ir->receiver_on) {
422386
if (iguanair_receiver(ir, true))
@@ -437,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev)
437401

438402
mutex_lock(&ir->lock);
439403

440-
usb_submit_urb(ir->urb_in, GFP_KERNEL);
441-
442404
BUG_ON(ir->receiver_on);
443405

444406
rc = iguanair_receiver(ir, true);
@@ -462,8 +424,6 @@ static void iguanair_close(struct rc_dev *rdev)
462424
if (rc)
463425
dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
464426

465-
usb_kill_urb(ir->urb_in);
466-
467427
mutex_unlock(&ir->lock);
468428
}
469429

@@ -473,7 +433,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
473433
struct usb_device *udev = interface_to_usbdev(intf);
474434
struct iguanair *ir;
475435
struct rc_dev *rc;
476-
int ret;
436+
int ret, pipein;
477437
struct usb_host_interface *idesc;
478438

479439
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
@@ -483,7 +443,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
483443
goto out;
484444
}
485445

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,
487447
&ir->dma_in);
488448
ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
489449

@@ -502,25 +462,28 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
502462
ir->rc = rc;
503463
ir->dev = &intf->dev;
504464
ir->udev = udev;
505-
ir->pipe_in = usb_rcvintpipe(udev,
506-
idesc->endpoint[0].desc.bEndpointAddress);
507465
ir->pipe_out = usb_sndintpipe(udev,
508466
idesc->endpoint[1].desc.bEndpointAddress);
509467
mutex_init(&ir->lock);
510468
init_completion(&ir->completion);
511469

512-
ret = iguanair_get_features(ir);
513-
if (ret) {
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,
470+
pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
471+
usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in,
519472
MAX_PACKET_SIZE, iguanair_rx, ir,
520473
idesc->endpoint[0].desc.bInterval);
521474
ir->urb_in->transfer_dma = ir->dma_in;
522475
ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
523476

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+
524487
snprintf(ir->name, sizeof(ir->name),
525488
"IguanaWorks USB IR Transceiver version %d.%d",
526489
ir->version[0], ir->version[1]);
@@ -547,14 +510,16 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
547510
ret = rc_register_device(rc);
548511
if (ret < 0) {
549512
dev_err(&intf->dev, "failed to register rc device %d", ret);
550-
goto out;
513+
goto out2;
551514
}
552515

553516
usb_set_intfdata(intf, ir);
554517

555518
dev_info(&intf->dev, "Registered %s", ir->name);
556519

557520
return 0;
521+
out2:
522+
usb_kill_urb(ir->urb_in);
558523
out:
559524
if (ir) {
560525
usb_free_urb(ir->urb_in);

0 commit comments

Comments
 (0)