/* poll IR chip */
size = i2c_master_recv(i2c_dev, buf, sizeof(buf));
if (size != 2) return -EIO;
/* Does eliminate repeated parity code */ if (buf[1] == 0xff) return 0;
/* * Rearranges bits to the right order. * The bit order were determined experimentally by using * The original Hauppauge Grey IR and another RC5 that uses addr=0x08 * The RC5 code has 14 bits, but we've experimentally determined * the meaning for only 11 bits. * So, the code translation is not complete. Yet, it is enough to * work with the provided RC5 IR.
*/
*protocol = RC_PROTO_RC5;
*scancode = (bitrev8(buf[1]) & 0x1f) << 8 | bitrev8(buf[0]) >> 2; return 1;
}
staticvoid em28xx_ir_handle_key(struct em28xx_IR *ir)
{ int result; struct em28xx_ir_poll_result poll_result;
/* read the registers containing the IR status */
result = ir->get_key(ir, &poll_result); if (unlikely(result < 0)) {
dprintk("ir->get_key() failed: %d\n", result); return;
}
if (ir->dev->chip_id == CHIP_ID_EM2874 ||
ir->dev->chip_id == CHIP_ID_EM2884) /* * The em2874 clears the readcount field every time the * register is read. The em2860/2880 datasheet says * that it is supposed to clear the readcount, but it * doesn't. So with the em2874, we are looking for a * non-zero read count as opposed to a readcount * that is incrementing
*/
ir->last_readcount = 0; else
ir->last_readcount = poll_result.read_count;
}
}
/* Setup the proper handler based on the chip */ switch (dev->chip_id) { case CHIP_ID_EM2860: case CHIP_ID_EM2883: return em2860_ir_change_protocol(rc_dev, rc_proto); case CHIP_ID_EM2884: case CHIP_ID_EM2874: case CHIP_ID_EM28174: case CHIP_ID_EM28178: return em2874_ir_change_protocol(rc_dev, rc_proto); default:
dev_err(&ir->dev->intf->dev, "Unrecognized em28xx chip id 0x%02x: IR not supported\n",
dev->chip_id); return -EINVAL;
}
}
staticint em28xx_probe_i2c_ir(struct em28xx *dev)
{ int i = 0; /* * Leadtek winfast tv USBII deluxe can find a non working IR-device * at address 0x18, so if that address is needed for another board in * the future, please put it after 0x1f.
*/ staticconstunsignedshort addr_list[] = {
0x1f, 0x30, 0x47, I2C_CLIENT_END
};
while (addr_list[i] != I2C_CLIENT_END) { if (i2c_probe_func_quick_read(&dev->i2c_adap[dev->def_i2c_bus],
addr_list[i]) == 1) return addr_list[i];
i++;
}
/* Poll and evaluate all addresses */ for (i = 0; i < dev->num_button_polling_addresses; i++) { /* Read value from register */
regval = em28xx_read_reg(dev, dev->button_polling_addresses[i]); if (regval < 0) continue; /* Check states of the buttons and act */
j = 0; while (dev->board.buttons[j].role >= 0 &&
dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) { conststruct em28xx_button *button;
button = &dev->board.buttons[j];
/* Check if button uses the current address */ if (button->reg_r != dev->button_polling_addresses[i]) {
j++; continue;
} /* Determine if button is and was pressed last time */
is_pressed = regval & button->mask;
was_pressed = dev->button_polling_last_values[i]
& button->mask; if (button->inverted) {
is_pressed = !is_pressed;
was_pressed = !was_pressed;
} /* Clear button state (if needed) */ if (is_pressed && button->reg_clearing)
em28xx_write_reg(dev, button->reg_clearing,
(~regval & button->mask)
| (regval & ~button->mask)); /* Handle button state */ if (!is_pressed || was_pressed) {
j++; continue;
} switch (button->role) { case EM28XX_BUTTON_SNAPSHOT: /* Emulate the keypress */
input_report_key(dev->sbutton_input_dev,
EM28XX_SNAPSHOT_KEY, 1); /* Unpress the key */
input_report_key(dev->sbutton_input_dev,
EM28XX_SNAPSHOT_KEY, 0); break; case EM28XX_BUTTON_ILLUMINATION:
led = em28xx_find_led(dev,
EM28XX_LED_ILLUMINATION); /* Switch illumination LED on/off */ if (led)
em28xx_toggle_reg_bits(dev,
led->gpio_reg,
led->gpio_mask); break; default:
WARN_ONCE(1, "BUG: unhandled button role.");
} /* Next button */
j++;
} /* Save current value for comparison during the next polling */
dev->button_polling_last_values[i] = regval;
} /* Schedule next poll */
schedule_delayed_work(&dev->buttons_query_work,
msecs_to_jiffies(dev->button_polling_interval));
}
/* Check if polling address is already on the list */
addr_new = true; for (j = 0; j < dev->num_button_polling_addresses; j++) { if (button->reg_r == dev->button_polling_addresses[j]) {
addr_new = false; break;
}
} /* Check if max. number of polling addresses is exceeded */ if (addr_new && dev->num_button_polling_addresses
>= EM28XX_NUM_BUTTON_ADDRESSES_MAX) {
WARN_ONCE(1, "BUG: maximum number of button polling addresses exceeded."); goto next_button;
} /* Button role specific checks and actions */ if (button->role == EM28XX_BUTTON_SNAPSHOT) { /* Register input device */ if (em28xx_register_snapshot_button(dev) < 0) goto next_button;
} elseif (button->role == EM28XX_BUTTON_ILLUMINATION) { /* Check sanity */ if (!em28xx_find_led(dev, EM28XX_LED_ILLUMINATION)) {
dev_err(&dev->intf->dev, "BUG: illumination button defined, but no illumination LED.\n"); goto next_button;
}
} /* Add read address to list of polling addresses */ if (addr_new) { unsignedint index = dev->num_button_polling_addresses;
dev->button_polling_addresses[index] = button->reg_r;
dev->num_button_polling_addresses++;
} /* Reduce polling interval if necessary */ if (!button->reg_clearing)
dev->button_polling_interval =
EM28XX_BUTTONS_VOLATILE_QUERY_INTERVAL;
next_button: /* Next button */
i++;
}
if (dev->board.has_ir_i2c) {
i2c_rc_dev_addr = em28xx_probe_i2c_ir(dev); if (!i2c_rc_dev_addr) {
dev->board.has_ir_i2c = 0;
dev_warn(&dev->intf->dev, "No i2c IR remote control device found.\n");
err = -ENODEV; goto ref_put;
}
}
if (!dev->board.ir_codes && !dev->board.has_ir_i2c) { /* No remote control support */
dev_warn(&dev->intf->dev, "Remote control support is not available for this card.\n"); return 0;
}
dev_info(&dev->intf->dev, "Suspending input extension\n"); if (ir)
cancel_delayed_work_sync(&ir->work);
cancel_delayed_work_sync(&dev->buttons_query_work); /* * is canceling delayed work sufficient or does the rc event * kthread needs stopping? kthread is stopped in * ir_raw_event_unregister()
*/ return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.