| /* |
| * i2c IR lirc driver for devices with zilog IR processors |
| * |
| * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> |
| * modified for PixelView (BT878P+W/FM) by |
| * Michal Kochanowicz <mkochano@pld.org.pl> |
| * Christoph Bartelmus <lirc@bartelmus.de> |
| * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by |
| * Ulrich Mueller <ulrich.mueller42@web.de> |
| * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by |
| * Stefan Jahn <stefan@lkcc.org> |
| * modified for inclusion into kernel sources by |
| * Jerome Brock <jbrock@users.sourceforge.net> |
| * modified for Leadtek Winfast PVR2000 by |
| * Thomas Reitmayr (treitmayr@yahoo.com) |
| * modified for Hauppauge PVR-150 IR TX device by |
| * Mark Weaver <mark@npsl.co.uk> |
| * changed name from lirc_pvr150 to lirc_zilog, works on more than pvr-150 |
| * Jarod Wilson <jarod@redhat.com> |
| * |
| * parts are cut&pasted from the lirc_i2c.c driver |
| * |
| * Numerous changes updating lirc_zilog.c in kernel 2.6.38 and later are |
| * Copyright (C) 2011 Andy Walls <awalls@md.metrocast.net> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/kmod.h> |
| #include <linux/kernel.h> |
| #include <linux/sched/signal.h> |
| #include <linux/fs.h> |
| #include <linux/poll.h> |
| #include <linux/string.h> |
| #include <linux/timer.h> |
| #include <linux/delay.h> |
| #include <linux/completion.h> |
| #include <linux/errno.h> |
| #include <linux/slab.h> |
| #include <linux/i2c.h> |
| #include <linux/firmware.h> |
| #include <linux/vmalloc.h> |
| |
| #include <linux/mutex.h> |
| #include <linux/kthread.h> |
| |
| #include <media/lirc_dev.h> |
| #include <media/lirc.h> |
| |
| /* Max transfer size done by I2C transfer functions */ |
| #define MAX_XFER_SIZE 64 |
| |
| struct IR; |
| |
| struct IR_rx { |
| struct kref ref; |
| struct IR *ir; |
| |
| /* RX device */ |
| struct mutex client_lock; |
| struct i2c_client *c; |
| |
| /* RX polling thread data */ |
| struct task_struct *task; |
| |
| /* RX read data */ |
| unsigned char b[3]; |
| bool hdpvr_data_fmt; |
| }; |
| |
| struct IR_tx { |
| struct kref ref; |
| struct IR *ir; |
| |
| /* TX device */ |
| struct mutex client_lock; |
| struct i2c_client *c; |
| |
| /* TX additional actions needed */ |
| int need_boot; |
| bool post_tx_ready_poll; |
| }; |
| |
| struct IR { |
| struct kref ref; |
| struct list_head list; |
| |
| /* FIXME spinlock access to l.features */ |
| struct lirc_driver l; |
| struct lirc_buffer rbuf; |
| |
| struct mutex ir_lock; |
| atomic_t open_count; |
| |
| struct i2c_adapter *adapter; |
| |
| spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */ |
| struct IR_rx *rx; |
| |
| spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */ |
| struct IR_tx *tx; |
| }; |
| |
| /* IR transceiver instance object list */ |
| /* |
| * This lock is used for the following: |
| * a. ir_devices_list access, insertions, deletions |
| * b. struct IR kref get()s and put()s |
| * c. serialization of ir_probe() for the two i2c_clients for a Z8 |
| */ |
| static DEFINE_MUTEX(ir_devices_lock); |
| static LIST_HEAD(ir_devices_list); |
| |
| /* Block size for IR transmitter */ |
| #define TX_BLOCK_SIZE 99 |
| |
| /* Hauppauge IR transmitter data */ |
| struct tx_data_struct { |
| /* Boot block */ |
| unsigned char *boot_data; |
| |
| /* Start of binary data block */ |
| unsigned char *datap; |
| |
| /* End of binary data block */ |
| unsigned char *endp; |
| |
| /* Number of installed codesets */ |
| unsigned int num_code_sets; |
| |
| /* Pointers to codesets */ |
| unsigned char **code_sets; |
| |
| /* Global fixed data template */ |
| int fixed[TX_BLOCK_SIZE]; |
| }; |
| |
| static struct tx_data_struct *tx_data; |
| static struct mutex tx_data_lock; |
| |
| |
| /* module parameters */ |
| static bool debug; /* debug output */ |
| static bool tx_only; /* only handle the IR Tx function */ |
| |
| |
| /* struct IR reference counting */ |
| static struct IR *get_ir_device(struct IR *ir, bool ir_devices_lock_held) |
| { |
| if (ir_devices_lock_held) { |
| kref_get(&ir->ref); |
| } else { |
| mutex_lock(&ir_devices_lock); |
| kref_get(&ir->ref); |
| mutex_unlock(&ir_devices_lock); |
| } |
| return ir; |
| } |
| |
| static void release_ir_device(struct kref *ref) |
| { |
| struct IR *ir = container_of(ref, struct IR, ref); |
| |
| /* |
| * Things should be in this state by now: |
| * ir->rx set to NULL and deallocated - happens before ir->rx->ir put() |
| * ir->rx->task kthread stopped - happens before ir->rx->ir put() |
| * ir->tx set to NULL and deallocated - happens before ir->tx->ir put() |
| * ir->open_count == 0 - happens on final close() |
| * ir_lock, tx_ref_lock, rx_ref_lock, all released |
| */ |
| if (ir->l.minor >= 0) { |
| lirc_unregister_driver(ir->l.minor); |
| ir->l.minor = -1; |
| } |
| |
| if (kfifo_initialized(&ir->rbuf.fifo)) |
| lirc_buffer_free(&ir->rbuf); |
| list_del(&ir->list); |
| kfree(ir); |
| } |
| |
| static int put_ir_device(struct IR *ir, bool ir_devices_lock_held) |
| { |
| int released; |
| |
| if (ir_devices_lock_held) |
| return kref_put(&ir->ref, release_ir_device); |
| |
| mutex_lock(&ir_devices_lock); |
| released = kref_put(&ir->ref, release_ir_device); |
| mutex_unlock(&ir_devices_lock); |
| |
| return released; |
| } |
| |
| /* struct IR_rx reference counting */ |
| static struct IR_rx *get_ir_rx(struct IR *ir) |
| { |
| struct IR_rx *rx; |
| |
| spin_lock(&ir->rx_ref_lock); |
| rx = ir->rx; |
| if (rx) |
| kref_get(&rx->ref); |
| spin_unlock(&ir->rx_ref_lock); |
| return rx; |
| } |
| |
| static void destroy_rx_kthread(struct IR_rx *rx, bool ir_devices_lock_held) |
| { |
| /* end up polling thread */ |
| if (!IS_ERR_OR_NULL(rx->task)) { |
| kthread_stop(rx->task); |
| rx->task = NULL; |
| /* Put the ir ptr that ir_probe() gave to the rx poll thread */ |
| put_ir_device(rx->ir, ir_devices_lock_held); |
| } |
| } |
| |
| static void release_ir_rx(struct kref *ref) |
| { |
| struct IR_rx *rx = container_of(ref, struct IR_rx, ref); |
| struct IR *ir = rx->ir; |
| |
| /* |
| * This release function can't do all the work, as we want |
| * to keep the rx_ref_lock a spinlock, and killing the poll thread |
| * and releasing the ir reference can cause a sleep. That work is |
| * performed by put_ir_rx() |
| */ |
| ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; |
| /* Don't put_ir_device(rx->ir) here; lock can't be freed yet */ |
| ir->rx = NULL; |
| /* Don't do the kfree(rx) here; we still need to kill the poll thread */ |
| } |
| |
| static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held) |
| { |
| int released; |
| struct IR *ir = rx->ir; |
| |
| spin_lock(&ir->rx_ref_lock); |
| released = kref_put(&rx->ref, release_ir_rx); |
| spin_unlock(&ir->rx_ref_lock); |
| /* Destroy the rx kthread while not holding the spinlock */ |
| if (released) { |
| destroy_rx_kthread(rx, ir_devices_lock_held); |
| kfree(rx); |
| /* Make sure we're not still in a poll_table somewhere */ |
| wake_up_interruptible(&ir->rbuf.wait_poll); |
| } |
| /* Do a reference put() for the rx->ir reference, if we released rx */ |
| if (released) |
| put_ir_device(ir, ir_devices_lock_held); |
| return released; |
| } |
| |
| /* struct IR_tx reference counting */ |
| static struct IR_tx *get_ir_tx(struct IR *ir) |
| { |
| struct IR_tx *tx; |
| |
| spin_lock(&ir->tx_ref_lock); |
| tx = ir->tx; |
| if (tx) |
| kref_get(&tx->ref); |
| spin_unlock(&ir->tx_ref_lock); |
| return tx; |
| } |
| |
| static void release_ir_tx(struct kref *ref) |
| { |
| struct IR_tx *tx = container_of(ref, struct IR_tx, ref); |
| struct IR *ir = tx->ir; |
| |
| ir->l.features &= ~LIRC_CAN_SEND_LIRCCODE; |
| /* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */ |
| ir->tx = NULL; |
| kfree(tx); |
| } |
| |
| static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held) |
| { |
| int released; |
| struct IR *ir = tx->ir; |
| |
| spin_lock(&ir->tx_ref_lock); |
| released = kref_put(&tx->ref, release_ir_tx); |
| spin_unlock(&ir->tx_ref_lock); |
| /* Do a reference put() for the tx->ir reference, if we released tx */ |
| if (released) |
| put_ir_device(ir, ir_devices_lock_held); |
| return released; |
| } |
| |
| static int add_to_buf(struct IR *ir) |
| { |
| __u16 code; |
| unsigned char codes[2]; |
| unsigned char keybuf[6]; |
| int got_data = 0; |
| int ret; |
| int failures = 0; |
| unsigned char sendbuf[1] = { 0 }; |
| struct lirc_buffer *rbuf = ir->l.rbuf; |
| struct IR_rx *rx; |
| struct IR_tx *tx; |
| |
| if (lirc_buffer_full(rbuf)) { |
| dev_dbg(ir->l.dev, "buffer overflow\n"); |
| return -EOVERFLOW; |
| } |
| |
| rx = get_ir_rx(ir); |
| if (!rx) |
| return -ENXIO; |
| |
| /* Ensure our rx->c i2c_client remains valid for the duration */ |
| mutex_lock(&rx->client_lock); |
| if (!rx->c) { |
| mutex_unlock(&rx->client_lock); |
| put_ir_rx(rx, false); |
| return -ENXIO; |
| } |
| |
| tx = get_ir_tx(ir); |
| |
| /* |
| * service the device as long as it is returning |
| * data and we have space |
| */ |
| do { |
| if (kthread_should_stop()) { |
| ret = -ENODATA; |
| break; |
| } |
| |
| /* |
| * Lock i2c bus for the duration. RX/TX chips interfere so |
| * this is worth it |
| */ |
| mutex_lock(&ir->ir_lock); |
| |
| if (kthread_should_stop()) { |
| mutex_unlock(&ir->ir_lock); |
| ret = -ENODATA; |
| break; |
| } |
| |
| /* |
| * Send random "poll command" (?) Windows driver does this |
| * and it is a good point to detect chip failure. |
| */ |
| ret = i2c_master_send(rx->c, sendbuf, 1); |
| if (ret != 1) { |
| dev_err(ir->l.dev, "i2c_master_send failed with %d\n", |
| ret); |
| if (failures >= 3) { |
| mutex_unlock(&ir->ir_lock); |
| dev_err(ir->l.dev, |
| "unable to read from the IR chip after 3 resets, giving up\n"); |
| break; |
| } |
| |
| /* Looks like the chip crashed, reset it */ |
| dev_err(ir->l.dev, |
| "polling the IR receiver chip failed, trying reset\n"); |
| |
| set_current_state(TASK_UNINTERRUPTIBLE); |
| if (kthread_should_stop()) { |
| mutex_unlock(&ir->ir_lock); |
| ret = -ENODATA; |
| break; |
| } |
| schedule_timeout((100 * HZ + 999) / 1000); |
| if (tx) |
| tx->need_boot = 1; |
| |
| ++failures; |
| mutex_unlock(&ir->ir_lock); |
| ret = 0; |
| continue; |
| } |
| |
| if (kthread_should_stop()) { |
| mutex_unlock(&ir->ir_lock); |
| ret = -ENODATA; |
| break; |
| } |
| ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf)); |
| mutex_unlock(&ir->ir_lock); |
| if (ret != sizeof(keybuf)) { |
| dev_err(ir->l.dev, |
| "i2c_master_recv failed with %d -- keeping last read buffer\n", |
| ret); |
| } else { |
| rx->b[0] = keybuf[3]; |
| rx->b[1] = keybuf[4]; |
| rx->b[2] = keybuf[5]; |
| dev_dbg(ir->l.dev, |
| "key (0x%02x/0x%02x)\n", |
| rx->b[0], rx->b[1]); |
| } |
| |
| /* key pressed ? */ |
| if (rx->hdpvr_data_fmt) { |
| if (got_data && (keybuf[0] == 0x80)) { |
| ret = 0; |
| break; |
| } else if (got_data && (keybuf[0] == 0x00)) { |
| ret = -ENODATA; |
| break; |
| } |
| } else if ((rx->b[0] & 0x80) == 0) { |
| ret = got_data ? 0 : -ENODATA; |
| break; |
| } |
| |
| /* look what we have */ |
| code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2); |
| |
| codes[0] = (code >> 8) & 0xff; |
| codes[1] = code & 0xff; |
| |
| /* return it */ |
| lirc_buffer_write(rbuf, codes); |
| ++got_data; |
| ret = 0; |
| } while (!lirc_buffer_full(rbuf)); |
| |
| mutex_unlock(&rx->client_lock); |
| if (tx) |
| put_ir_tx(tx, false); |
| put_ir_rx(rx, false); |
| return ret; |
| } |
| |
| /* |
| * Main function of the polling thread -- from lirc_dev. |
| * We don't fit the LIRC model at all anymore. This is horrible, but |
| * basically we have a single RX/TX device with a nasty failure mode |
| * that needs to be accounted for across the pair. lirc lets us provide |
| * fops, but prevents us from using the internal polling, etc. if we do |
| * so. Hence the replication. Might be neater to extend the LIRC model |
| * to account for this but I'd think it's a very special case of seriously |
| * messed up hardware. |
| */ |
| static int lirc_thread(void *arg) |
| { |
| struct IR *ir = arg; |
| struct lirc_buffer *rbuf = ir->l.rbuf; |
| |
| dev_dbg(ir->l.dev, "poll thread started\n"); |
| |
| while (!kthread_should_stop()) { |
| set_current_state(TASK_INTERRUPTIBLE); |
| |
| /* if device not opened, we can sleep half a second */ |
| if (atomic_read(&ir->open_count) == 0) { |
| schedule_timeout(HZ / 2); |
| continue; |
| } |
| |
| /* |
| * This is ~113*2 + 24 + jitter (2*repeat gap + code length). |
| * We use this interval as the chip resets every time you poll |
| * it (bad!). This is therefore just sufficient to catch all |
| * of the button presses. It makes the remote much more |
| * responsive. You can see the difference by running irw and |
| * holding down a button. With 100ms, the old polling |
| * interval, you'll notice breaks in the repeat sequence |
| * corresponding to lost keypresses. |
| */ |
| schedule_timeout((260 * HZ) / 1000); |
| if (kthread_should_stop()) |
| break; |
| if (!add_to_buf(ir)) |
| wake_up_interruptible(&rbuf->wait_poll); |
| } |
| |
| dev_dbg(ir->l.dev, "poll thread ended\n"); |
| return 0; |
| } |
| |
| /* safe read of a uint32 (always network byte order) */ |
| static int read_uint32(unsigned char **data, |
| unsigned char *endp, unsigned int *val) |
| { |
| if (*data + 4 > endp) |
| return 0; |
| *val = ((*data)[0] << 24) | ((*data)[1] << 16) | |
| ((*data)[2] << 8) | (*data)[3]; |
| *data += 4; |
| return 1; |
| } |
| |
| /* safe read of a uint8 */ |
| static int read_uint8(unsigned char **data, |
| unsigned char *endp, unsigned char *val) |
| { |
| if (*data + 1 > endp) |
| return 0; |
| *val = *((*data)++); |
| return 1; |
| } |
| |
| /* safe skipping of N bytes */ |
| static int skip(unsigned char **data, |
| unsigned char *endp, unsigned int distance) |
| { |
| if (*data + distance > endp) |
| return 0; |
| *data += distance; |
| return 1; |
| } |
| |
| /* decompress key data into the given buffer */ |
| static int get_key_data(unsigned char *buf, |
| unsigned int codeset, unsigned int key) |
| { |
| unsigned char *data, *endp, *diffs, *key_block; |
| unsigned char keys, ndiffs, id; |
| unsigned int base, lim, pos, i; |
| |
| /* Binary search for the codeset */ |
| for (base = 0, lim = tx_data->num_code_sets; lim; lim >>= 1) { |
| pos = base + (lim >> 1); |
| data = tx_data->code_sets[pos]; |
| |
| if (!read_uint32(&data, tx_data->endp, &i)) |
| goto corrupt; |
| |
| if (i == codeset) { |
| break; |
| } else if (codeset > i) { |
| base = pos + 1; |
| --lim; |
| } |
| } |
| /* Not found? */ |
| if (!lim) |
| return -EPROTO; |
| |
| /* Set end of data block */ |
| endp = pos < tx_data->num_code_sets - 1 ? |
| tx_data->code_sets[pos + 1] : tx_data->endp; |
| |
| /* Read the block header */ |
| if (!read_uint8(&data, endp, &keys) || |
| !read_uint8(&data, endp, &ndiffs) || |
| ndiffs > TX_BLOCK_SIZE || keys == 0) |
| goto corrupt; |
| |
| /* Save diffs & skip */ |
| diffs = data; |
| if (!skip(&data, endp, ndiffs)) |
| goto corrupt; |
| |
| /* Read the id of the first key */ |
| if (!read_uint8(&data, endp, &id)) |
| goto corrupt; |
| |
| /* Unpack the first key's data */ |
| for (i = 0; i < TX_BLOCK_SIZE; ++i) { |
| if (tx_data->fixed[i] == -1) { |
| if (!read_uint8(&data, endp, &buf[i])) |
| goto corrupt; |
| } else { |
| buf[i] = (unsigned char)tx_data->fixed[i]; |
| } |
| } |
| |
| /* Early out key found/not found */ |
| if (key == id) |
| return 0; |
| if (keys == 1) |
| return -EPROTO; |
| |
| /* Sanity check */ |
| key_block = data; |
| if (!skip(&data, endp, (keys - 1) * (ndiffs + 1))) |
| goto corrupt; |
| |
| /* Binary search for the key */ |
| for (base = 0, lim = keys - 1; lim; lim >>= 1) { |
| /* Seek to block */ |
| unsigned char *key_data; |
| |
| pos = base + (lim >> 1); |
| key_data = key_block + (ndiffs + 1) * pos; |
| |
| if (*key_data == key) { |
| /* skip key id */ |
| ++key_data; |
| |
| /* found, so unpack the diffs */ |
| for (i = 0; i < ndiffs; ++i) { |
| unsigned char val; |
| |
| if (!read_uint8(&key_data, endp, &val) || |
| diffs[i] >= TX_BLOCK_SIZE) |
| goto corrupt; |
| buf[diffs[i]] = val; |
| } |
| |
| return 0; |
| } else if (key > *key_data) { |
| base = pos + 1; |
| --lim; |
| } |
| } |
| /* Key not found */ |
| return -EPROTO; |
| |
| corrupt: |
| pr_err("firmware is corrupt\n"); |
| return -EFAULT; |
| } |
| |
| /* send a block of data to the IR TX device */ |
| static int send_data_block(struct IR_tx *tx, unsigned char *data_block) |
| { |
| int i, j, ret; |
| unsigned char buf[5]; |
| |
| for (i = 0; i < TX_BLOCK_SIZE;) { |
| int tosend = TX_BLOCK_SIZE - i; |
| |
| if (tosend > 4) |
| tosend = 4; |
| buf[0] = (unsigned char)(i + 1); |
| for (j = 0; j < tosend; ++j) |
| buf[1 + j] = data_block[i + j]; |
| dev_dbg(tx->ir->l.dev, "%*ph", 5, buf); |
| ret = i2c_master_send(tx->c, buf, tosend + 1); |
| if (ret != tosend + 1) { |
| dev_err(tx->ir->l.dev, |
| "i2c_master_send failed with %d\n", ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| i += tosend; |
| } |
| return 0; |
| } |
| |
| /* send boot data to the IR TX device */ |
| static int send_boot_data(struct IR_tx *tx) |
| { |
| int ret, i; |
| unsigned char buf[4]; |
| |
| /* send the boot block */ |
| ret = send_data_block(tx, tx_data->boot_data); |
| if (ret != 0) |
| return ret; |
| |
| /* Hit the go button to activate the new boot data */ |
| buf[0] = 0x00; |
| buf[1] = 0x20; |
| ret = i2c_master_send(tx->c, buf, 2); |
| if (ret != 2) { |
| dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| |
| /* |
| * Wait for zilog to settle after hitting go post boot block upload. |
| * Without this delay, the HD-PVR and HVR-1950 both return an -EIO |
| * upon attempting to get firmware revision, and tx probe thus fails. |
| */ |
| for (i = 0; i < 10; i++) { |
| ret = i2c_master_send(tx->c, buf, 1); |
| if (ret == 1) |
| break; |
| udelay(100); |
| } |
| |
| if (ret != 1) { |
| dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| |
| /* Here comes the firmware version... (hopefully) */ |
| ret = i2c_master_recv(tx->c, buf, 4); |
| if (ret != 4) { |
| dev_err(tx->ir->l.dev, "i2c_master_recv failed with %d\n", ret); |
| return 0; |
| } |
| if ((buf[0] != 0x80) && (buf[0] != 0xa0)) { |
| dev_err(tx->ir->l.dev, "unexpected IR TX init response: %02x\n", |
| buf[0]); |
| return 0; |
| } |
| dev_notice(tx->ir->l.dev, |
| "Zilog/Hauppauge IR blaster firmware version %d.%d.%d loaded\n", |
| buf[1], buf[2], buf[3]); |
| |
| return 0; |
| } |
| |
| /* unload "firmware", lock held */ |
| static void fw_unload_locked(void) |
| { |
| if (tx_data) { |
| vfree(tx_data->code_sets); |
| |
| vfree(tx_data->datap); |
| |
| vfree(tx_data); |
| tx_data = NULL; |
| pr_debug("successfully unloaded IR blaster firmware\n"); |
| } |
| } |
| |
| /* unload "firmware" for the IR TX device */ |
| static void fw_unload(void) |
| { |
| mutex_lock(&tx_data_lock); |
| fw_unload_locked(); |
| mutex_unlock(&tx_data_lock); |
| } |
| |
| /* load "firmware" for the IR TX device */ |
| static int fw_load(struct IR_tx *tx) |
| { |
| int ret; |
| unsigned int i; |
| unsigned char *data, version, num_global_fixed; |
| const struct firmware *fw_entry; |
| |
| /* Already loaded? */ |
| mutex_lock(&tx_data_lock); |
| if (tx_data) { |
| ret = 0; |
| goto out; |
| } |
| |
| /* Request codeset data file */ |
| ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev); |
| if (ret != 0) { |
| dev_err(tx->ir->l.dev, |
| "firmware haup-ir-blaster.bin not available (%d)\n", |
| ret); |
| ret = ret < 0 ? ret : -EFAULT; |
| goto out; |
| } |
| dev_dbg(tx->ir->l.dev, "firmware of size %zu loaded\n", fw_entry->size); |
| |
| /* Parse the file */ |
| tx_data = vmalloc(sizeof(*tx_data)); |
| if (!tx_data) { |
| release_firmware(fw_entry); |
| ret = -ENOMEM; |
| goto out; |
| } |
| tx_data->code_sets = NULL; |
| |
| /* Copy the data so hotplug doesn't get confused and timeout */ |
| tx_data->datap = vmalloc(fw_entry->size); |
| if (!tx_data->datap) { |
| release_firmware(fw_entry); |
| vfree(tx_data); |
| ret = -ENOMEM; |
| goto out; |
| } |
| memcpy(tx_data->datap, fw_entry->data, fw_entry->size); |
| tx_data->endp = tx_data->datap + fw_entry->size; |
| release_firmware(fw_entry); fw_entry = NULL; |
| |
| /* Check version */ |
| data = tx_data->datap; |
| if (!read_uint8(&data, tx_data->endp, &version)) |
| goto corrupt; |
| if (version != 1) { |
| dev_err(tx->ir->l.dev, |
| "unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver\n", |
| version); |
| fw_unload_locked(); |
| ret = -EFAULT; |
| goto out; |
| } |
| |
| /* Save boot block for later */ |
| tx_data->boot_data = data; |
| if (!skip(&data, tx_data->endp, TX_BLOCK_SIZE)) |
| goto corrupt; |
| |
| if (!read_uint32(&data, tx_data->endp, |
| &tx_data->num_code_sets)) |
| goto corrupt; |
| |
| dev_dbg(tx->ir->l.dev, "%u IR blaster codesets loaded\n", |
| tx_data->num_code_sets); |
| |
| tx_data->code_sets = vmalloc( |
| tx_data->num_code_sets * sizeof(char *)); |
| if (!tx_data->code_sets) { |
| fw_unload_locked(); |
| ret = -ENOMEM; |
| goto out; |
| } |
| |
| for (i = 0; i < TX_BLOCK_SIZE; ++i) |
| tx_data->fixed[i] = -1; |
| |
| /* Read global fixed data template */ |
| if (!read_uint8(&data, tx_data->endp, &num_global_fixed) || |
| num_global_fixed > TX_BLOCK_SIZE) |
| goto corrupt; |
| for (i = 0; i < num_global_fixed; ++i) { |
| unsigned char pos, val; |
| |
| if (!read_uint8(&data, tx_data->endp, &pos) || |
| !read_uint8(&data, tx_data->endp, &val) || |
| pos >= TX_BLOCK_SIZE) |
| goto corrupt; |
| tx_data->fixed[pos] = (int)val; |
| } |
| |
| /* Filch out the position of each code set */ |
| for (i = 0; i < tx_data->num_code_sets; ++i) { |
| unsigned int id; |
| unsigned char keys; |
| unsigned char ndiffs; |
| |
| /* Save the codeset position */ |
| tx_data->code_sets[i] = data; |
| |
| /* Read header */ |
| if (!read_uint32(&data, tx_data->endp, &id) || |
| !read_uint8(&data, tx_data->endp, &keys) || |
| !read_uint8(&data, tx_data->endp, &ndiffs) || |
| ndiffs > TX_BLOCK_SIZE || keys == 0) |
| goto corrupt; |
| |
| /* skip diff positions */ |
| if (!skip(&data, tx_data->endp, ndiffs)) |
| goto corrupt; |
| |
| /* |
| * After the diffs we have the first key id + data - |
| * global fixed |
| */ |
| if (!skip(&data, tx_data->endp, |
| 1 + TX_BLOCK_SIZE - num_global_fixed)) |
| goto corrupt; |
| |
| /* Then we have keys-1 blocks of key id+diffs */ |
| if (!skip(&data, tx_data->endp, |
| (ndiffs + 1) * (keys - 1))) |
| goto corrupt; |
| } |
| ret = 0; |
| goto out; |
| |
| corrupt: |
| dev_err(tx->ir->l.dev, "firmware is corrupt\n"); |
| fw_unload_locked(); |
| ret = -EFAULT; |
| |
| out: |
| mutex_unlock(&tx_data_lock); |
| return ret; |
| } |
| |
| /* copied from lirc_dev */ |
| static ssize_t read(struct file *filep, char __user *outbuf, size_t n, |
| loff_t *ppos) |
| { |
| struct IR *ir = filep->private_data; |
| struct IR_rx *rx; |
| struct lirc_buffer *rbuf = ir->l.rbuf; |
| int ret = 0, written = 0, retries = 0; |
| unsigned int m; |
| DECLARE_WAITQUEUE(wait, current); |
| |
| dev_dbg(ir->l.dev, "read called\n"); |
| if (n % rbuf->chunk_size) { |
| dev_dbg(ir->l.dev, "read result = -EINVAL\n"); |
| return -EINVAL; |
| } |
| |
| rx = get_ir_rx(ir); |
| if (!rx) |
| return -ENXIO; |
| |
| /* |
| * we add ourselves to the task queue before buffer check |
| * to avoid losing scan code (in case when queue is awaken somewhere |
| * between while condition checking and scheduling) |
| */ |
| add_wait_queue(&rbuf->wait_poll, &wait); |
| set_current_state(TASK_INTERRUPTIBLE); |
| |
| /* |
| * while we didn't provide 'length' bytes, device is opened in blocking |
| * mode and 'copy_to_user' is happy, wait for data. |
| */ |
| while (written < n && ret == 0) { |
| if (lirc_buffer_empty(rbuf)) { |
| /* |
| * According to the read(2) man page, 'written' can be |
| * returned as less than 'n', instead of blocking |
| * again, returning -EWOULDBLOCK, or returning |
| * -ERESTARTSYS |
| */ |
| if (written) |
| break; |
| if (filep->f_flags & O_NONBLOCK) { |
| ret = -EWOULDBLOCK; |
| break; |
| } |
| if (signal_pending(current)) { |
| ret = -ERESTARTSYS; |
| break; |
| } |
| schedule(); |
| set_current_state(TASK_INTERRUPTIBLE); |
| } else { |
| unsigned char buf[MAX_XFER_SIZE]; |
| |
| if (rbuf->chunk_size > sizeof(buf)) { |
| dev_err(ir->l.dev, |
| "chunk_size is too big (%d)!\n", |
| rbuf->chunk_size); |
| ret = -EINVAL; |
| break; |
| } |
| m = lirc_buffer_read(rbuf, buf); |
| if (m == rbuf->chunk_size) { |
| ret = copy_to_user(outbuf + written, buf, |
| rbuf->chunk_size); |
| written += rbuf->chunk_size; |
| } else { |
| retries++; |
| } |
| if (retries >= 5) { |
| dev_err(ir->l.dev, "Buffer read failed!\n"); |
| ret = -EIO; |
| } |
| } |
| } |
| |
| remove_wait_queue(&rbuf->wait_poll, &wait); |
| put_ir_rx(rx, false); |
| set_current_state(TASK_RUNNING); |
| |
| dev_dbg(ir->l.dev, "read result = %d (%s)\n", ret, |
| ret ? "Error" : "OK"); |
| |
| return ret ? ret : written; |
| } |
| |
| /* send a keypress to the IR TX device */ |
| static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) |
| { |
| unsigned char data_block[TX_BLOCK_SIZE]; |
| unsigned char buf[2]; |
| int i, ret; |
| |
| /* Get data for the codeset/key */ |
| ret = get_key_data(data_block, code, key); |
| |
| if (ret == -EPROTO) { |
| dev_err(tx->ir->l.dev, |
| "failed to get data for code %u, key %u -- check lircd.conf entries\n", |
| code, key); |
| return ret; |
| } else if (ret != 0) { |
| return ret; |
| } |
| |
| /* Send the data block */ |
| ret = send_data_block(tx, data_block); |
| if (ret != 0) |
| return ret; |
| |
| /* Send data block length? */ |
| buf[0] = 0x00; |
| buf[1] = 0x40; |
| ret = i2c_master_send(tx->c, buf, 2); |
| if (ret != 2) { |
| dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| |
| /* Give the z8 a moment to process data block */ |
| for (i = 0; i < 10; i++) { |
| ret = i2c_master_send(tx->c, buf, 1); |
| if (ret == 1) |
| break; |
| udelay(100); |
| } |
| |
| if (ret != 1) { |
| dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| |
| /* Send finished download? */ |
| ret = i2c_master_recv(tx->c, buf, 1); |
| if (ret != 1) { |
| dev_err(tx->ir->l.dev, "i2c_master_recv failed with %d\n", ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| if (buf[0] != 0xA0) { |
| dev_err(tx->ir->l.dev, "unexpected IR TX response #1: %02x\n", |
| buf[0]); |
| return -EFAULT; |
| } |
| |
| /* Send prepare command? */ |
| buf[0] = 0x00; |
| buf[1] = 0x80; |
| ret = i2c_master_send(tx->c, buf, 2); |
| if (ret != 2) { |
| dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| |
| /* |
| * The sleep bits aren't necessary on the HD PVR, and in fact, the |
| * last i2c_master_recv always fails with a -5, so for now, we're |
| * going to skip this whole mess and say we're done on the HD PVR |
| */ |
| if (!tx->post_tx_ready_poll) { |
| dev_dbg(tx->ir->l.dev, "sent code %u, key %u\n", code, key); |
| return 0; |
| } |
| |
| /* |
| * This bit NAKs until the device is ready, so we retry it |
| * sleeping a bit each time. This seems to be what the windows |
| * driver does, approximately. |
| * Try for up to 1s. |
| */ |
| for (i = 0; i < 20; ++i) { |
| set_current_state(TASK_UNINTERRUPTIBLE); |
| schedule_timeout((50 * HZ + 999) / 1000); |
| ret = i2c_master_send(tx->c, buf, 1); |
| if (ret == 1) |
| break; |
| dev_dbg(tx->ir->l.dev, |
| "NAK expected: i2c_master_send failed with %d (try %d)\n", |
| ret, i + 1); |
| } |
| if (ret != 1) { |
| dev_err(tx->ir->l.dev, |
| "IR TX chip never got ready: last i2c_master_send failed with %d\n", |
| ret); |
| return ret < 0 ? ret : -EFAULT; |
| } |
| |
| /* Seems to be an 'ok' response */ |
| i = i2c_master_recv(tx->c, buf, 1); |
| if (i != 1) { |
| dev_err(tx->ir->l.dev, "i2c_master_recv failed with %d\n", ret); |
| return -EFAULT; |
| } |
| if (buf[0] != 0x80) { |
| dev_err(tx->ir->l.dev, "unexpected IR TX response #2: %02x\n", |
| buf[0]); |
| return -EFAULT; |
| } |
| |
| /* Oh good, it worked */ |
| dev_dbg(tx->ir->l.dev, "sent code %u, key %u\n", code, key); |
| return 0; |
| } |
| |
| /* |
| * Write a code to the device. We take in a 32-bit number (an int) and then |
| * decode this to a codeset/key index. The key data is then decompressed and |
| * sent to the device. We have a spin lock as per i2c documentation to prevent |
| * multiple concurrent sends which would probably cause the device to explode. |
| */ |
| static ssize_t write(struct file *filep, const char __user *buf, size_t n, |
| loff_t *ppos) |
| { |
| struct IR *ir = filep->private_data; |
| struct IR_tx *tx; |
| size_t i; |
| int failures = 0; |
| |
| /* Validate user parameters */ |
| if (n % sizeof(int)) |
| return -EINVAL; |
| |
| /* Get a struct IR_tx reference */ |
| tx = get_ir_tx(ir); |
| if (!tx) |
| return -ENXIO; |
| |
| /* Ensure our tx->c i2c_client remains valid for the duration */ |
| mutex_lock(&tx->client_lock); |
| if (!tx->c) { |
| mutex_unlock(&tx->client_lock); |
| put_ir_tx(tx, false); |
| return -ENXIO; |
| } |
| |
| /* Lock i2c bus for the duration */ |
| mutex_lock(&ir->ir_lock); |
| |
| /* Send each keypress */ |
| for (i = 0; i < n;) { |
| int ret = 0; |
| int command; |
| |
| if (copy_from_user(&command, buf + i, sizeof(command))) { |
| mutex_unlock(&ir->ir_lock); |
| mutex_unlock(&tx->client_lock); |
| put_ir_tx(tx, false); |
| return -EFAULT; |
| } |
| |
| /* Send boot data first if required */ |
| if (tx->need_boot == 1) { |
| /* Make sure we have the 'firmware' loaded, first */ |
| ret = fw_load(tx); |
| if (ret != 0) { |
| mutex_unlock(&ir->ir_lock); |
| mutex_unlock(&tx->client_lock); |
| put_ir_tx(tx, false); |
| if (ret != -ENOMEM) |
| ret = -EIO; |
| return ret; |
| } |
| /* Prep the chip for transmitting codes */ |
| ret = send_boot_data(tx); |
| if (ret == 0) |
| tx->need_boot = 0; |
| } |
| |
| /* Send the code */ |
| if (ret == 0) { |
| ret = send_code(tx, (unsigned int)command >> 16, |
| (unsigned int)command & 0xFFFF); |
| if (ret == -EPROTO) { |
| mutex_unlock(&ir->ir_lock); |
| mutex_unlock(&tx->client_lock); |
| put_ir_tx(tx, false); |
| return ret; |
| } |
| } |
| |
| /* |
| * Hmm, a failure. If we've had a few then give up, otherwise |
| * try a reset |
| */ |
| if (ret != 0) { |
| /* Looks like the chip crashed, reset it */ |
| dev_err(tx->ir->l.dev, |
| "sending to the IR transmitter chip failed, trying reset\n"); |
| |
| if (failures >= 3) { |
| dev_err(tx->ir->l.dev, |
| "unable to send to the IR chip after 3 resets, giving up\n"); |
| mutex_unlock(&ir->ir_lock); |
| mutex_unlock(&tx->client_lock); |
| put_ir_tx(tx, false); |
| return ret; |
| } |
| set_current_state(TASK_UNINTERRUPTIBLE); |
| schedule_timeout((100 * HZ + 999) / 1000); |
| tx->need_boot = 1; |
| ++failures; |
| } else { |
| i += sizeof(int); |
| } |
| } |
| |
| /* Release i2c bus */ |
| mutex_unlock(&ir->ir_lock); |
| |
| mutex_unlock(&tx->client_lock); |
| |
| /* Give back our struct IR_tx reference */ |
| put_ir_tx(tx, false); |
| |
| /* All looks good */ |
| return n; |
| } |
| |
| /* copied from lirc_dev */ |
| static unsigned int poll(struct file *filep, poll_table *wait) |
| { |
| struct IR *ir = filep->private_data; |
| struct IR_rx *rx; |
| struct lirc_buffer *rbuf = ir->l.rbuf; |
| unsigned int ret; |
| |
| dev_dbg(ir->l.dev, "%s called\n", __func__); |
| |
| rx = get_ir_rx(ir); |
| if (!rx) { |
| /* |
| * Revisit this, if our poll function ever reports writeable |
| * status for Tx |
| */ |
| dev_dbg(ir->l.dev, "%s result = POLLERR\n", __func__); |
| return POLLERR; |
| } |
| |
| /* |
| * Add our lirc_buffer's wait_queue to the poll_table. A wake up on |
| * that buffer's wait queue indicates we may have a new poll status. |
| */ |
| poll_wait(filep, &rbuf->wait_poll, wait); |
| |
| /* Indicate what ops could happen immediately without blocking */ |
| ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN | POLLRDNORM); |
| |
| dev_dbg(ir->l.dev, "%s result = %s\n", __func__, |
| ret ? "POLLIN|POLLRDNORM" : "none"); |
| return ret; |
| } |
| |
| static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) |
| { |
| struct IR *ir = filep->private_data; |
| unsigned long __user *uptr = (unsigned long __user *)arg; |
| int result; |
| unsigned long mode, features; |
| |
| features = ir->l.features; |
| |
| switch (cmd) { |
| case LIRC_GET_LENGTH: |
| result = put_user(13UL, uptr); |
| break; |
| case LIRC_GET_FEATURES: |
| result = put_user(features, uptr); |
| break; |
| case LIRC_GET_REC_MODE: |
| if (!(features & LIRC_CAN_REC_MASK)) |
| return -ENOTTY; |
| |
| result = put_user(LIRC_REC2MODE |
| (features & LIRC_CAN_REC_MASK), |
| uptr); |
| break; |
| case LIRC_SET_REC_MODE: |
| if (!(features & LIRC_CAN_REC_MASK)) |
| return -ENOTTY; |
| |
| result = get_user(mode, uptr); |
| if (!result && !(LIRC_MODE2REC(mode) & features)) |
| result = -ENOTTY; |
| break; |
| case LIRC_GET_SEND_MODE: |
| if (!(features & LIRC_CAN_SEND_MASK)) |
| return -ENOTTY; |
| |
| result = put_user(LIRC_MODE_LIRCCODE, uptr); |
| break; |
| case LIRC_SET_SEND_MODE: |
| if (!(features & LIRC_CAN_SEND_MASK)) |
| return -ENOTTY; |
| |
| result = get_user(mode, uptr); |
| if (!result && mode != LIRC_MODE_LIRCCODE) |
| return -EINVAL; |
| break; |
| default: |
| return -EINVAL; |
| } |
| return result; |
| } |
| |
| static struct IR *get_ir_device_by_minor(unsigned int minor) |
| { |
| struct IR *ir; |
| struct IR *ret = NULL; |
| |
| mutex_lock(&ir_devices_lock); |
| |
| if (!list_empty(&ir_devices_list)) { |
| list_for_each_entry(ir, &ir_devices_list, list) { |
| if (ir->l.minor == minor) { |
| ret = get_ir_device(ir, true); |
| break; |
| } |
| } |
| } |
| |
| mutex_unlock(&ir_devices_lock); |
| return ret; |
| } |
| |
| /* |
| * Open the IR device. Get hold of our IR structure and |
| * stash it in private_data for the file |
| */ |
| static int open(struct inode *node, struct file *filep) |
| { |
| struct IR *ir; |
| unsigned int minor = MINOR(node->i_rdev); |
| |
| /* find our IR struct */ |
| ir = get_ir_device_by_minor(minor); |
| |
| if (!ir) |
| return -ENODEV; |
| |
| atomic_inc(&ir->open_count); |
| |
| /* stash our IR struct */ |
| filep->private_data = ir; |
| |
| nonseekable_open(node, filep); |
| return 0; |
| } |
| |
| /* Close the IR device */ |
| static int close(struct inode *node, struct file *filep) |
| { |
| /* find our IR struct */ |
| struct IR *ir = filep->private_data; |
| |
| if (!ir) { |
| pr_err("ir: %s: no private_data attached to the file!\n", |
| __func__); |
| return -ENODEV; |
| } |
| |
| atomic_dec(&ir->open_count); |
| |
| put_ir_device(ir, false); |
| return 0; |
| } |
| |
| static int ir_remove(struct i2c_client *client); |
| static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); |
| |
| #define ID_FLAG_TX 0x01 |
| #define ID_FLAG_HDPVR 0x02 |
| |
| static const struct i2c_device_id ir_transceiver_id[] = { |
| { "ir_tx_z8f0811_haup", ID_FLAG_TX }, |
| { "ir_rx_z8f0811_haup", 0 }, |
| { "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX }, |
| { "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR }, |
| { } |
| }; |
| MODULE_DEVICE_TABLE(i2c, ir_transceiver_id); |
| |
| static struct i2c_driver driver = { |
| .driver = { |
| .name = "Zilog/Hauppauge i2c IR", |
| }, |
| .probe = ir_probe, |
| .remove = ir_remove, |
| .id_table = ir_transceiver_id, |
| }; |
| |
| static const struct file_operations lirc_fops = { |
| .owner = THIS_MODULE, |
| .llseek = no_llseek, |
| .read = read, |
| .write = write, |
| .poll = poll, |
| .unlocked_ioctl = ioctl, |
| #ifdef CONFIG_COMPAT |
| .compat_ioctl = ioctl, |
| #endif |
| .open = open, |
| .release = close |
| }; |
| |
| static struct lirc_driver lirc_template = { |
| .name = "lirc_zilog", |
| .minor = -1, |
| .code_length = 13, |
| .buffer_size = BUFLEN / 2, |
| .chunk_size = 2, |
| .fops = &lirc_fops, |
| .owner = THIS_MODULE, |
| }; |
| |
| static int ir_remove(struct i2c_client *client) |
| { |
| if (strncmp("ir_tx_z8", client->name, 8) == 0) { |
| struct IR_tx *tx = i2c_get_clientdata(client); |
| |
| if (tx) { |
| mutex_lock(&tx->client_lock); |
| tx->c = NULL; |
| mutex_unlock(&tx->client_lock); |
| put_ir_tx(tx, false); |
| } |
| } else if (strncmp("ir_rx_z8", client->name, 8) == 0) { |
| struct IR_rx *rx = i2c_get_clientdata(client); |
| |
| if (rx) { |
| mutex_lock(&rx->client_lock); |
| rx->c = NULL; |
| mutex_unlock(&rx->client_lock); |
| put_ir_rx(rx, false); |
| } |
| } |
| return 0; |
| } |
| |
| /* ir_devices_lock must be held */ |
| static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter) |
| { |
| struct IR *ir; |
| |
| if (list_empty(&ir_devices_list)) |
| return NULL; |
| |
| list_for_each_entry(ir, &ir_devices_list, list) |
| if (ir->adapter == adapter) { |
| get_ir_device(ir, true); |
| return ir; |
| } |
| |
| return NULL; |
| } |
| |
| static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) |
| { |
| struct IR *ir; |
| struct IR_tx *tx; |
| struct IR_rx *rx; |
| struct i2c_adapter *adap = client->adapter; |
| int ret; |
| bool tx_probe = false; |
| |
| dev_dbg(&client->dev, "%s: %s on i2c-%d (%s), client addr=0x%02x\n", |
| __func__, id->name, adap->nr, adap->name, client->addr); |
| |
| /* |
| * The IR receiver is at i2c address 0x71. |
| * The IR transmitter is at i2c address 0x70. |
| */ |
| |
| if (id->driver_data & ID_FLAG_TX) |
| tx_probe = true; |
| else if (tx_only) /* module option */ |
| return -ENXIO; |
| |
| pr_info("probing IR %s on %s (i2c-%d)\n", |
| tx_probe ? "Tx" : "Rx", adap->name, adap->nr); |
| |
| mutex_lock(&ir_devices_lock); |
| |
| /* Use a single struct IR instance for both the Rx and Tx functions */ |
| ir = get_ir_device_by_adapter(adap); |
| if (!ir) { |
| ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
| if (!ir) { |
| ret = -ENOMEM; |
| goto out_no_ir; |
| } |
| kref_init(&ir->ref); |
| |
| /* store for use in ir_probe() again, and open() later on */ |
| INIT_LIST_HEAD(&ir->list); |
| list_add_tail(&ir->list, &ir_devices_list); |
| |
| ir->adapter = adap; |
| mutex_init(&ir->ir_lock); |
| atomic_set(&ir->open_count, 0); |
| spin_lock_init(&ir->tx_ref_lock); |
| spin_lock_init(&ir->rx_ref_lock); |
| |
| /* set lirc_dev stuff */ |
| memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); |
| /* |
| * FIXME this is a pointer reference to us, but no refcount. |
| * |
| * This OK for now, since lirc_dev currently won't touch this |
| * buffer as we provide our own lirc_fops. |
| * |
| * Currently our own lirc_fops rely on this ir->l.rbuf pointer |
| */ |
| ir->l.rbuf = &ir->rbuf; |
| ir->l.dev = &adap->dev; |
| ret = lirc_buffer_init(ir->l.rbuf, |
| ir->l.chunk_size, ir->l.buffer_size); |
| if (ret) |
| goto out_put_ir; |
| } |
| |
| if (tx_probe) { |
| /* Get the IR_rx instance for later, if already allocated */ |
| rx = get_ir_rx(ir); |
| |
| /* Set up a struct IR_tx instance */ |
| tx = kzalloc(sizeof(*tx), GFP_KERNEL); |
| if (!tx) { |
| ret = -ENOMEM; |
| goto out_put_xx; |
| } |
| kref_init(&tx->ref); |
| ir->tx = tx; |
| |
| ir->l.features |= LIRC_CAN_SEND_LIRCCODE; |
| mutex_init(&tx->client_lock); |
| tx->c = client; |
| tx->need_boot = 1; |
| tx->post_tx_ready_poll = |
| (id->driver_data & ID_FLAG_HDPVR) ? false : true; |
| |
| /* An ir ref goes to the struct IR_tx instance */ |
| tx->ir = get_ir_device(ir, true); |
| |
| /* A tx ref goes to the i2c_client */ |
| i2c_set_clientdata(client, get_ir_tx(ir)); |
| |
| /* |
| * Load the 'firmware'. We do this before registering with |
| * lirc_dev, so the first firmware load attempt does not happen |
| * after a open() or write() call on the device. |
| * |
| * Failure here is not deemed catastrophic, so the receiver will |
| * still be usable. Firmware load will be retried in write(), |
| * if it is needed. |
| */ |
| fw_load(tx); |
| |
| /* Proceed only if the Rx client is also ready or not needed */ |
| if (!rx && !tx_only) { |
| dev_info(tx->ir->l.dev, |
| "probe of IR Tx on %s (i2c-%d) done. Waiting on IR Rx.\n", |
| adap->name, adap->nr); |
| goto out_ok; |
| } |
| } else { |
| /* Get the IR_tx instance for later, if already allocated */ |
| tx = get_ir_tx(ir); |
| |
| /* Set up a struct IR_rx instance */ |
| rx = kzalloc(sizeof(*rx), GFP_KERNEL); |
| if (!rx) { |
| ret = -ENOMEM; |
| goto out_put_xx; |
| } |
| kref_init(&rx->ref); |
| ir->rx = rx; |
| |
| ir->l.features |= LIRC_CAN_REC_LIRCCODE; |
| mutex_init(&rx->client_lock); |
| rx->c = client; |
| rx->hdpvr_data_fmt = |
| (id->driver_data & ID_FLAG_HDPVR) ? true : false; |
| |
| /* An ir ref goes to the struct IR_rx instance */ |
| rx->ir = get_ir_device(ir, true); |
| |
| /* An rx ref goes to the i2c_client */ |
| i2c_set_clientdata(client, get_ir_rx(ir)); |
| |
| /* |
| * Start the polling thread. |
| * It will only perform an empty loop around schedule_timeout() |
| * until we register with lirc_dev and the first user open() |
| */ |
| /* An ir ref goes to the new rx polling kthread */ |
| rx->task = kthread_run(lirc_thread, get_ir_device(ir, true), |
| "zilog-rx-i2c-%d", adap->nr); |
| if (IS_ERR(rx->task)) { |
| ret = PTR_ERR(rx->task); |
| dev_err(tx->ir->l.dev, |
| "%s: could not start IR Rx polling thread\n", |
| __func__); |
| /* Failed kthread, so put back the ir ref */ |
| put_ir_device(ir, true); |
| /* Failure exit, so put back rx ref from i2c_client */ |
| i2c_set_clientdata(client, NULL); |
| put_ir_rx(rx, true); |
| ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; |
| goto out_put_tx; |
| } |
| |
| /* Proceed only if the Tx client is also ready */ |
| if (!tx) { |
| pr_info("probe of IR Rx on %s (i2c-%d) done. Waiting on IR Tx.\n", |
| adap->name, adap->nr); |
| goto out_ok; |
| } |
| } |
| |
| /* register with lirc */ |
| ir->l.minor = lirc_register_driver(&ir->l); |
| if (ir->l.minor < 0) { |
| dev_err(tx->ir->l.dev, |
| "%s: lirc_register_driver() failed: %i\n", |
| __func__, ir->l.minor); |
| ret = -EBADRQC; |
| goto out_put_xx; |
| } |
| dev_info(ir->l.dev, |
| "IR unit on %s (i2c-%d) registered as lirc%d and ready\n", |
| adap->name, adap->nr, ir->l.minor); |
| |
| out_ok: |
| if (rx) |
| put_ir_rx(rx, true); |
| if (tx) |
| put_ir_tx(tx, true); |
| put_ir_device(ir, true); |
| dev_info(ir->l.dev, |
| "probe of IR %s on %s (i2c-%d) done\n", |
| tx_probe ? "Tx" : "Rx", adap->name, adap->nr); |
| mutex_unlock(&ir_devices_lock); |
| return 0; |
| |
| out_put_xx: |
| if (rx) |
| put_ir_rx(rx, true); |
| out_put_tx: |
| if (tx) |
| put_ir_tx(tx, true); |
| out_put_ir: |
| put_ir_device(ir, true); |
| out_no_ir: |
| dev_err(&client->dev, |
| "%s: probing IR %s on %s (i2c-%d) failed with %d\n", |
| __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, ret); |
| mutex_unlock(&ir_devices_lock); |
| return ret; |
| } |
| |
| static int __init zilog_init(void) |
| { |
| int ret; |
| |
| pr_notice("Zilog/Hauppauge IR driver initializing\n"); |
| |
| mutex_init(&tx_data_lock); |
| |
| request_module("firmware_class"); |
| |
| ret = i2c_add_driver(&driver); |
| if (ret) |
| pr_err("initialization failed\n"); |
| else |
| pr_notice("initialization complete\n"); |
| |
| return ret; |
| } |
| |
| static void __exit zilog_exit(void) |
| { |
| i2c_del_driver(&driver); |
| /* if loaded */ |
| fw_unload(); |
| pr_notice("Zilog/Hauppauge IR driver unloaded\n"); |
| } |
| |
| module_init(zilog_init); |
| module_exit(zilog_exit); |
| |
| MODULE_DESCRIPTION("Zilog/Hauppauge infrared transmitter driver (i2c stack)"); |
| MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver, Andy Walls"); |
| MODULE_LICENSE("GPL"); |
| /* for compat with old name, which isn't all that accurate anymore */ |
| MODULE_ALIAS("lirc_pvr150"); |
| |
| module_param(debug, bool, 0644); |
| MODULE_PARM_DESC(debug, "Enable debugging messages"); |
| |
| module_param(tx_only, bool, 0644); |
| MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function"); |