Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 181480
b: refs/heads/master
c: 6a20710
h: refs/heads/master
v: v3
  • Loading branch information
Devin Heitmueller authored and Mauro Carvalho Chehab committed Feb 26, 2010
1 parent 9ca3a24 commit f1f04a8
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 152 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eac8f5fa5f5dcaf228694fe23e19b02b98e68879
refs/heads/master: 6a2071006b72bf887e38c025c60f98d2998ceacb
1 change: 0 additions & 1 deletion trunk/drivers/media/dvb/dvb-usb/dib0700.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ struct dib0700_state {
u16 mt2060_if1[2];
u8 rc_toggle;
u8 rc_counter;
u8 rc_func_version;
u8 is_dib7000pc;
u8 fw_use_new_i2c_api;
u8 disable_streaming_master_mode;
Expand Down
196 changes: 195 additions & 1 deletion trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,14 +471,208 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return dib0700_ctrl_wr(adap->dev, b, 4);
}

/* Number of keypresses to ignore before start repeating */
#define RC_REPEAT_DELAY_V1_20 10

/* This is the structure of the RC response packet starting in firmware 1.20 */
struct dib0700_rc_response {
u8 report_id;
u8 data_state;
u16 system;
u8 data;
u8 not_data;
};
#define RC_MSG_SIZE_V1_20 6

static void dib0700_rc_urb_completion(struct urb *purb)
{
struct dvb_usb_device *d = purb->context;
struct dvb_usb_rc_key *keymap;
struct dib0700_state *st;
struct dib0700_rc_response poll_reply;
u8 *buf;
int found = 0;
u32 event;
int state;
int i;

deb_info("%s()\n", __func__);
if (d == NULL)
return;

if (d->rc_input_dev == NULL) {
/* This will occur if disable_rc_polling=1 */
usb_free_urb(purb);
return;
}

keymap = d->props.rc_key_map;
st = d->priv;
buf = (u8 *)purb->transfer_buffer;

if (purb->status < 0) {
deb_info("discontinuing polling\n");
usb_free_urb(purb);
return;
}

if (purb->actual_length != RC_MSG_SIZE_V1_20) {
deb_info("malformed rc msg size=%d\n", purb->actual_length);
goto resubmit;
}

/* Set initial results in case we exit the function early */
event = 0;
state = REMOTE_NO_KEY_PRESSED;

deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0],
buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length);

switch (dvb_usb_dib0700_ir_proto) {
case 0:
/* NEC Protocol */
poll_reply.report_id = 0;
poll_reply.data_state = 1;
poll_reply.system = buf[2];
poll_reply.data = buf[4];
poll_reply.not_data = buf[5];

/* NEC protocol sends repeat code as 0 0 0 FF */
if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
&& (poll_reply.not_data == 0xff)) {
poll_reply.data_state = 2;
break;
}
break;
default:
/* RC5 Protocol */
poll_reply.report_id = buf[0];
poll_reply.data_state = buf[1];
poll_reply.system = (buf[2] << 8) | buf[3];
poll_reply.data = buf[4];
poll_reply.not_data = buf[5];
break;
}

if ((poll_reply.data + poll_reply.not_data) != 0xff) {
/* Key failed integrity check */
err("key failed integrity check: %04x %02x %02x",
poll_reply.system,
poll_reply.data, poll_reply.not_data);
goto resubmit;
}

deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n",
poll_reply.report_id, poll_reply.data_state,
poll_reply.system, poll_reply.data, poll_reply.not_data);

/* Find the key in the map */
for (i = 0; i < d->props.rc_key_map_size; i++) {
if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
rc5_data(&keymap[i]) == poll_reply.data) {
event = keymap[i].event;
found = 1;
break;
}
}

if (found == 0) {
err("Unknown remote controller key: %04x %02x %02x",
poll_reply.system, poll_reply.data, poll_reply.not_data);
d->last_event = 0;
goto resubmit;
}

if (poll_reply.data_state == 1) {
/* New key hit */
st->rc_counter = 0;
event = keymap[i].event;
state = REMOTE_KEY_PRESSED;
d->last_event = keymap[i].event;
} else if (poll_reply.data_state == 2) {
/* Key repeated */
st->rc_counter++;

/* prevents unwanted double hits */
if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
event = d->last_event;
state = REMOTE_KEY_PRESSED;
st->rc_counter = RC_REPEAT_DELAY_V1_20;
}
} else {
err("Unknown data state [%d]", poll_reply.data_state);
}

switch (state) {
case REMOTE_NO_KEY_PRESSED:
break;
case REMOTE_KEY_PRESSED:
deb_info("key pressed\n");
d->last_event = event;
case REMOTE_KEY_REPEAT:
deb_info("key repeated\n");
input_event(d->rc_input_dev, EV_KEY, event, 1);
input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
input_sync(d->rc_input_dev);
break;
default:
break;
}

resubmit:
/* Clean the buffer before we requeue */
memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20);

/* Requeue URB */
usb_submit_urb(purb, GFP_ATOMIC);
}

int dib0700_rc_setup(struct dvb_usb_device *d)
{
struct dib0700_state *st = d->priv;
u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
int i = dib0700_ctrl_wr(d, rc_setup, 3);
struct urb *purb;
int ret;
int i;

if (d->props.rc_key_map == NULL)
return 0;

/* Set the IR mode */
i = dib0700_ctrl_wr(d, rc_setup, 3);
if (i<0) {
err("ir protocol setup failed");
return -1;
}

if (st->fw_version < 0x10200)
return 0;

/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
purb = usb_alloc_urb(0, GFP_KERNEL);
if (purb == NULL) {
err("rc usb alloc urb failed\n");
return -1;
}

purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
if (purb->transfer_buffer == NULL) {
err("rc kzalloc failed\n");
usb_free_urb(purb);
return -1;
}

purb->status = -EINPROGRESS;
usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1),
purb->transfer_buffer, RC_MSG_SIZE_V1_20,
dib0700_rc_urb_completion, d);

ret = usb_submit_urb(purb, GFP_ATOMIC);
if (ret != 0) {
err("rc submit urb failed\n");
return -1;
}

return 0;
}

Expand Down
Loading

0 comments on commit f1f04a8

Please sign in to comment.