162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * keyspan_remote: USB driver for the Keyspan DMR 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005 Zymeta Corporation - Michael Downey (downey@zymeta.com) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This driver has been put together with the support of Innosys, Inc. 862306a36Sopenharmony_ci * and Keyspan, Inc the manufacturers of the Keyspan USB DMR product. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/errno.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/usb/input.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* Parameters that can be passed to the driver. */ 1862306a36Sopenharmony_cistatic int debug; 1962306a36Sopenharmony_cimodule_param(debug, int, 0444); 2062306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "Enable extra debug messages and information"); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* Vendor and product ids */ 2362306a36Sopenharmony_ci#define USB_KEYSPAN_VENDOR_ID 0x06CD 2462306a36Sopenharmony_ci#define USB_KEYSPAN_PRODUCT_UIA11 0x0202 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* Defines for converting the data from the remote. */ 2762306a36Sopenharmony_ci#define ZERO 0x18 2862306a36Sopenharmony_ci#define ZERO_MASK 0x1F /* 5 bits for a 0 */ 2962306a36Sopenharmony_ci#define ONE 0x3C 3062306a36Sopenharmony_ci#define ONE_MASK 0x3F /* 6 bits for a 1 */ 3162306a36Sopenharmony_ci#define SYNC 0x3F80 3262306a36Sopenharmony_ci#define SYNC_MASK 0x3FFF /* 14 bits for a SYNC sequence */ 3362306a36Sopenharmony_ci#define STOP 0x00 3462306a36Sopenharmony_ci#define STOP_MASK 0x1F /* 5 bits for the STOP sequence */ 3562306a36Sopenharmony_ci#define GAP 0xFF 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * Table that maps the 31 possible keycodes to input keys. 4162306a36Sopenharmony_ci * Currently there are 15 and 17 button models so RESERVED codes 4262306a36Sopenharmony_ci * are blank areas in the mapping. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_cistatic const unsigned short keyspan_key_table[] = { 4562306a36Sopenharmony_ci KEY_RESERVED, /* 0 is just a place holder. */ 4662306a36Sopenharmony_ci KEY_RESERVED, 4762306a36Sopenharmony_ci KEY_STOP, 4862306a36Sopenharmony_ci KEY_PLAYCD, 4962306a36Sopenharmony_ci KEY_RESERVED, 5062306a36Sopenharmony_ci KEY_PREVIOUSSONG, 5162306a36Sopenharmony_ci KEY_REWIND, 5262306a36Sopenharmony_ci KEY_FORWARD, 5362306a36Sopenharmony_ci KEY_NEXTSONG, 5462306a36Sopenharmony_ci KEY_RESERVED, 5562306a36Sopenharmony_ci KEY_RESERVED, 5662306a36Sopenharmony_ci KEY_RESERVED, 5762306a36Sopenharmony_ci KEY_PAUSE, 5862306a36Sopenharmony_ci KEY_VOLUMEUP, 5962306a36Sopenharmony_ci KEY_RESERVED, 6062306a36Sopenharmony_ci KEY_RESERVED, 6162306a36Sopenharmony_ci KEY_RESERVED, 6262306a36Sopenharmony_ci KEY_VOLUMEDOWN, 6362306a36Sopenharmony_ci KEY_RESERVED, 6462306a36Sopenharmony_ci KEY_UP, 6562306a36Sopenharmony_ci KEY_RESERVED, 6662306a36Sopenharmony_ci KEY_MUTE, 6762306a36Sopenharmony_ci KEY_LEFT, 6862306a36Sopenharmony_ci KEY_ENTER, 6962306a36Sopenharmony_ci KEY_RIGHT, 7062306a36Sopenharmony_ci KEY_RESERVED, 7162306a36Sopenharmony_ci KEY_RESERVED, 7262306a36Sopenharmony_ci KEY_DOWN, 7362306a36Sopenharmony_ci KEY_RESERVED, 7462306a36Sopenharmony_ci KEY_KPASTERISK, 7562306a36Sopenharmony_ci KEY_RESERVED, 7662306a36Sopenharmony_ci KEY_MENU 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* table of devices that work with this driver */ 8062306a36Sopenharmony_cistatic const struct usb_device_id keyspan_table[] = { 8162306a36Sopenharmony_ci { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, 8262306a36Sopenharmony_ci { } /* Terminating entry */ 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/* Structure to store all the real stuff that a remote sends to us. */ 8662306a36Sopenharmony_cistruct keyspan_message { 8762306a36Sopenharmony_ci u16 system; 8862306a36Sopenharmony_ci u8 button; 8962306a36Sopenharmony_ci u8 toggle; 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* Structure used for all the bit testing magic needed to be done. */ 9362306a36Sopenharmony_cistruct bit_tester { 9462306a36Sopenharmony_ci u32 tester; 9562306a36Sopenharmony_ci int len; 9662306a36Sopenharmony_ci int pos; 9762306a36Sopenharmony_ci int bits_left; 9862306a36Sopenharmony_ci u8 buffer[32]; 9962306a36Sopenharmony_ci}; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* Structure to hold all of our driver specific stuff */ 10262306a36Sopenharmony_cistruct usb_keyspan { 10362306a36Sopenharmony_ci char name[128]; 10462306a36Sopenharmony_ci char phys[64]; 10562306a36Sopenharmony_ci unsigned short keymap[ARRAY_SIZE(keyspan_key_table)]; 10662306a36Sopenharmony_ci struct usb_device *udev; 10762306a36Sopenharmony_ci struct input_dev *input; 10862306a36Sopenharmony_ci struct usb_interface *interface; 10962306a36Sopenharmony_ci struct usb_endpoint_descriptor *in_endpoint; 11062306a36Sopenharmony_ci struct urb* irq_urb; 11162306a36Sopenharmony_ci int open; 11262306a36Sopenharmony_ci dma_addr_t in_dma; 11362306a36Sopenharmony_ci unsigned char *in_buffer; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* variables used to parse messages from remote. */ 11662306a36Sopenharmony_ci struct bit_tester data; 11762306a36Sopenharmony_ci int stage; 11862306a36Sopenharmony_ci int toggle; 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic struct usb_driver keyspan_driver; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* 12462306a36Sopenharmony_ci * Debug routine that prints out what we've received from the remote. 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_cistatic void keyspan_print(struct usb_keyspan* dev) /*unsigned char* data)*/ 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci char codes[4 * RECV_SIZE]; 12962306a36Sopenharmony_ci int i; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci for (i = 0; i < RECV_SIZE; i++) 13262306a36Sopenharmony_ci snprintf(codes + i * 3, 4, "%02x ", dev->in_buffer[i]); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci dev_info(&dev->udev->dev, "%s\n", codes); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* 13862306a36Sopenharmony_ci * Routine that manages the bit_tester structure. It makes sure that there are 13962306a36Sopenharmony_ci * at least bits_needed bits loaded into the tester. 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_cistatic int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci if (dev->data.bits_left >= bits_needed) 14462306a36Sopenharmony_ci return 0; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* 14762306a36Sopenharmony_ci * Somehow we've missed the last message. The message will be repeated 14862306a36Sopenharmony_ci * though so it's not too big a deal 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_ci if (dev->data.pos >= dev->data.len) { 15162306a36Sopenharmony_ci dev_dbg(&dev->interface->dev, 15262306a36Sopenharmony_ci "%s - Error ran out of data. pos: %d, len: %d\n", 15362306a36Sopenharmony_ci __func__, dev->data.pos, dev->data.len); 15462306a36Sopenharmony_ci return -1; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci /* Load as much as we can into the tester. */ 15862306a36Sopenharmony_ci while ((dev->data.bits_left + 7 < (sizeof(dev->data.tester) * 8)) && 15962306a36Sopenharmony_ci (dev->data.pos < dev->data.len)) { 16062306a36Sopenharmony_ci dev->data.tester += (dev->data.buffer[dev->data.pos++] << dev->data.bits_left); 16162306a36Sopenharmony_ci dev->data.bits_left += 8; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci return 0; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic void keyspan_report_button(struct usb_keyspan *remote, int button, int press) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci struct input_dev *input = remote->input; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci input_event(input, EV_MSC, MSC_SCAN, button); 17262306a36Sopenharmony_ci input_report_key(input, remote->keymap[button], press); 17362306a36Sopenharmony_ci input_sync(input); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/* 17762306a36Sopenharmony_ci * Routine that handles all the logic needed to parse out the message from the remote. 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_cistatic void keyspan_check_data(struct usb_keyspan *remote) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci int i; 18262306a36Sopenharmony_ci int found = 0; 18362306a36Sopenharmony_ci struct keyspan_message message; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci switch(remote->stage) { 18662306a36Sopenharmony_ci case 0: 18762306a36Sopenharmony_ci /* 18862306a36Sopenharmony_ci * In stage 0 we want to find the start of a message. The remote sends a 0xFF as filler. 18962306a36Sopenharmony_ci * So the first byte that isn't a FF should be the start of a new message. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci for (i = 0; i < RECV_SIZE && remote->in_buffer[i] == GAP; ++i); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (i < RECV_SIZE) { 19462306a36Sopenharmony_ci memcpy(remote->data.buffer, remote->in_buffer, RECV_SIZE); 19562306a36Sopenharmony_ci remote->data.len = RECV_SIZE; 19662306a36Sopenharmony_ci remote->data.pos = 0; 19762306a36Sopenharmony_ci remote->data.tester = 0; 19862306a36Sopenharmony_ci remote->data.bits_left = 0; 19962306a36Sopenharmony_ci remote->stage = 1; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci break; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci case 1: 20462306a36Sopenharmony_ci /* 20562306a36Sopenharmony_ci * Stage 1 we should have 16 bytes and should be able to detect a 20662306a36Sopenharmony_ci * SYNC. The SYNC is 14 bits, 7 0's and then 7 1's. 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_ci memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); 20962306a36Sopenharmony_ci remote->data.len += RECV_SIZE; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci found = 0; 21262306a36Sopenharmony_ci while ((remote->data.bits_left >= 14 || remote->data.pos < remote->data.len) && !found) { 21362306a36Sopenharmony_ci for (i = 0; i < 8; ++i) { 21462306a36Sopenharmony_ci if (keyspan_load_tester(remote, 14) != 0) { 21562306a36Sopenharmony_ci remote->stage = 0; 21662306a36Sopenharmony_ci return; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if ((remote->data.tester & SYNC_MASK) == SYNC) { 22062306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 14; 22162306a36Sopenharmony_ci remote->data.bits_left -= 14; 22262306a36Sopenharmony_ci found = 1; 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci } else { 22562306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 1; 22662306a36Sopenharmony_ci --remote->data.bits_left; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci if (!found) { 23262306a36Sopenharmony_ci remote->stage = 0; 23362306a36Sopenharmony_ci remote->data.len = 0; 23462306a36Sopenharmony_ci } else { 23562306a36Sopenharmony_ci remote->stage = 2; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci break; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci case 2: 24062306a36Sopenharmony_ci /* 24162306a36Sopenharmony_ci * Stage 2 we should have 24 bytes which will be enough for a full 24262306a36Sopenharmony_ci * message. We need to parse out the system code, button code, 24362306a36Sopenharmony_ci * toggle code, and stop. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_ci memcpy(remote->data.buffer + remote->data.len, remote->in_buffer, RECV_SIZE); 24662306a36Sopenharmony_ci remote->data.len += RECV_SIZE; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci message.system = 0; 24962306a36Sopenharmony_ci for (i = 0; i < 9; i++) { 25062306a36Sopenharmony_ci keyspan_load_tester(remote, 6); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if ((remote->data.tester & ZERO_MASK) == ZERO) { 25362306a36Sopenharmony_ci message.system = message.system << 1; 25462306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 5; 25562306a36Sopenharmony_ci remote->data.bits_left -= 5; 25662306a36Sopenharmony_ci } else if ((remote->data.tester & ONE_MASK) == ONE) { 25762306a36Sopenharmony_ci message.system = (message.system << 1) + 1; 25862306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 6; 25962306a36Sopenharmony_ci remote->data.bits_left -= 6; 26062306a36Sopenharmony_ci } else { 26162306a36Sopenharmony_ci dev_err(&remote->interface->dev, 26262306a36Sopenharmony_ci "%s - Unknown sequence found in system data.\n", 26362306a36Sopenharmony_ci __func__); 26462306a36Sopenharmony_ci remote->stage = 0; 26562306a36Sopenharmony_ci return; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci message.button = 0; 27062306a36Sopenharmony_ci for (i = 0; i < 5; i++) { 27162306a36Sopenharmony_ci keyspan_load_tester(remote, 6); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if ((remote->data.tester & ZERO_MASK) == ZERO) { 27462306a36Sopenharmony_ci message.button = message.button << 1; 27562306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 5; 27662306a36Sopenharmony_ci remote->data.bits_left -= 5; 27762306a36Sopenharmony_ci } else if ((remote->data.tester & ONE_MASK) == ONE) { 27862306a36Sopenharmony_ci message.button = (message.button << 1) + 1; 27962306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 6; 28062306a36Sopenharmony_ci remote->data.bits_left -= 6; 28162306a36Sopenharmony_ci } else { 28262306a36Sopenharmony_ci dev_err(&remote->interface->dev, 28362306a36Sopenharmony_ci "%s - Unknown sequence found in button data.\n", 28462306a36Sopenharmony_ci __func__); 28562306a36Sopenharmony_ci remote->stage = 0; 28662306a36Sopenharmony_ci return; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci keyspan_load_tester(remote, 6); 29162306a36Sopenharmony_ci if ((remote->data.tester & ZERO_MASK) == ZERO) { 29262306a36Sopenharmony_ci message.toggle = 0; 29362306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 5; 29462306a36Sopenharmony_ci remote->data.bits_left -= 5; 29562306a36Sopenharmony_ci } else if ((remote->data.tester & ONE_MASK) == ONE) { 29662306a36Sopenharmony_ci message.toggle = 1; 29762306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 6; 29862306a36Sopenharmony_ci remote->data.bits_left -= 6; 29962306a36Sopenharmony_ci } else { 30062306a36Sopenharmony_ci dev_err(&remote->interface->dev, 30162306a36Sopenharmony_ci "%s - Error in message, invalid toggle.\n", 30262306a36Sopenharmony_ci __func__); 30362306a36Sopenharmony_ci remote->stage = 0; 30462306a36Sopenharmony_ci return; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci keyspan_load_tester(remote, 5); 30862306a36Sopenharmony_ci if ((remote->data.tester & STOP_MASK) == STOP) { 30962306a36Sopenharmony_ci remote->data.tester = remote->data.tester >> 5; 31062306a36Sopenharmony_ci remote->data.bits_left -= 5; 31162306a36Sopenharmony_ci } else { 31262306a36Sopenharmony_ci dev_err(&remote->interface->dev, 31362306a36Sopenharmony_ci "Bad message received, no stop bit found.\n"); 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci dev_dbg(&remote->interface->dev, 31762306a36Sopenharmony_ci "%s found valid message: system: %d, button: %d, toggle: %d\n", 31862306a36Sopenharmony_ci __func__, message.system, message.button, message.toggle); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (message.toggle != remote->toggle) { 32162306a36Sopenharmony_ci keyspan_report_button(remote, message.button, 1); 32262306a36Sopenharmony_ci keyspan_report_button(remote, message.button, 0); 32362306a36Sopenharmony_ci remote->toggle = message.toggle; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci remote->stage = 0; 32762306a36Sopenharmony_ci break; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci/* 33262306a36Sopenharmony_ci * Routine for sending all the initialization messages to the remote. 33362306a36Sopenharmony_ci */ 33462306a36Sopenharmony_cistatic int keyspan_setup(struct usb_device* dev) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci int retval = 0; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 33962306a36Sopenharmony_ci 0x11, 0x40, 0x5601, 0x0, NULL, 0, 34062306a36Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 34162306a36Sopenharmony_ci if (retval) { 34262306a36Sopenharmony_ci dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n", 34362306a36Sopenharmony_ci __func__, retval); 34462306a36Sopenharmony_ci return(retval); 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 34862306a36Sopenharmony_ci 0x44, 0x40, 0x0, 0x0, NULL, 0, 34962306a36Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 35062306a36Sopenharmony_ci if (retval) { 35162306a36Sopenharmony_ci dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n", 35262306a36Sopenharmony_ci __func__, retval); 35362306a36Sopenharmony_ci return(retval); 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 35762306a36Sopenharmony_ci 0x22, 0x40, 0x0, 0x0, NULL, 0, 35862306a36Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 35962306a36Sopenharmony_ci if (retval) { 36062306a36Sopenharmony_ci dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n", 36162306a36Sopenharmony_ci __func__, retval); 36262306a36Sopenharmony_ci return(retval); 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci dev_dbg(&dev->dev, "%s - Setup complete.\n", __func__); 36662306a36Sopenharmony_ci return(retval); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci/* 37062306a36Sopenharmony_ci * Routine used to handle a new message that has come in. 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_cistatic void keyspan_irq_recv(struct urb *urb) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci struct usb_keyspan *dev = urb->context; 37562306a36Sopenharmony_ci int retval; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* Check our status in case we need to bail out early. */ 37862306a36Sopenharmony_ci switch (urb->status) { 37962306a36Sopenharmony_ci case 0: 38062306a36Sopenharmony_ci break; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Device went away so don't keep trying to read from it. */ 38362306a36Sopenharmony_ci case -ECONNRESET: 38462306a36Sopenharmony_ci case -ENOENT: 38562306a36Sopenharmony_ci case -ESHUTDOWN: 38662306a36Sopenharmony_ci return; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci default: 38962306a36Sopenharmony_ci goto resubmit; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (debug) 39362306a36Sopenharmony_ci keyspan_print(dev); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci keyspan_check_data(dev); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ciresubmit: 39862306a36Sopenharmony_ci retval = usb_submit_urb(urb, GFP_ATOMIC); 39962306a36Sopenharmony_ci if (retval) 40062306a36Sopenharmony_ci dev_err(&dev->interface->dev, 40162306a36Sopenharmony_ci "%s - usb_submit_urb failed with result: %d\n", 40262306a36Sopenharmony_ci __func__, retval); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic int keyspan_open(struct input_dev *dev) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci struct usb_keyspan *remote = input_get_drvdata(dev); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci remote->irq_urb->dev = remote->udev; 41062306a36Sopenharmony_ci if (usb_submit_urb(remote->irq_urb, GFP_KERNEL)) 41162306a36Sopenharmony_ci return -EIO; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci return 0; 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_cistatic void keyspan_close(struct input_dev *dev) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci struct usb_keyspan *remote = input_get_drvdata(dev); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci usb_kill_urb(remote->irq_urb); 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_interface *iface) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci struct usb_endpoint_descriptor *endpoint; 42762306a36Sopenharmony_ci int i; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci for (i = 0; i < iface->desc.bNumEndpoints; ++i) { 43062306a36Sopenharmony_ci endpoint = &iface->endpoint[i].desc; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (usb_endpoint_is_int_in(endpoint)) { 43362306a36Sopenharmony_ci /* we found our interrupt in endpoint */ 43462306a36Sopenharmony_ci return endpoint; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci return NULL; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci/* 44262306a36Sopenharmony_ci * Routine that sets up the driver to handle a specific USB device detected on the bus. 44362306a36Sopenharmony_ci */ 44462306a36Sopenharmony_cistatic int keyspan_probe(struct usb_interface *interface, const struct usb_device_id *id) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(interface); 44762306a36Sopenharmony_ci struct usb_endpoint_descriptor *endpoint; 44862306a36Sopenharmony_ci struct usb_keyspan *remote; 44962306a36Sopenharmony_ci struct input_dev *input_dev; 45062306a36Sopenharmony_ci int i, error; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci endpoint = keyspan_get_in_endpoint(interface->cur_altsetting); 45362306a36Sopenharmony_ci if (!endpoint) 45462306a36Sopenharmony_ci return -ENODEV; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci remote = kzalloc(sizeof(*remote), GFP_KERNEL); 45762306a36Sopenharmony_ci input_dev = input_allocate_device(); 45862306a36Sopenharmony_ci if (!remote || !input_dev) { 45962306a36Sopenharmony_ci error = -ENOMEM; 46062306a36Sopenharmony_ci goto fail1; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci remote->udev = udev; 46462306a36Sopenharmony_ci remote->input = input_dev; 46562306a36Sopenharmony_ci remote->interface = interface; 46662306a36Sopenharmony_ci remote->in_endpoint = endpoint; 46762306a36Sopenharmony_ci remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_KERNEL, &remote->in_dma); 47062306a36Sopenharmony_ci if (!remote->in_buffer) { 47162306a36Sopenharmony_ci error = -ENOMEM; 47262306a36Sopenharmony_ci goto fail1; 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); 47662306a36Sopenharmony_ci if (!remote->irq_urb) { 47762306a36Sopenharmony_ci error = -ENOMEM; 47862306a36Sopenharmony_ci goto fail2; 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci error = keyspan_setup(udev); 48262306a36Sopenharmony_ci if (error) { 48362306a36Sopenharmony_ci error = -ENODEV; 48462306a36Sopenharmony_ci goto fail3; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if (udev->manufacturer) 48862306a36Sopenharmony_ci strscpy(remote->name, udev->manufacturer, sizeof(remote->name)); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (udev->product) { 49162306a36Sopenharmony_ci if (udev->manufacturer) 49262306a36Sopenharmony_ci strlcat(remote->name, " ", sizeof(remote->name)); 49362306a36Sopenharmony_ci strlcat(remote->name, udev->product, sizeof(remote->name)); 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci if (!strlen(remote->name)) 49762306a36Sopenharmony_ci snprintf(remote->name, sizeof(remote->name), 49862306a36Sopenharmony_ci "USB Keyspan Remote %04x:%04x", 49962306a36Sopenharmony_ci le16_to_cpu(udev->descriptor.idVendor), 50062306a36Sopenharmony_ci le16_to_cpu(udev->descriptor.idProduct)); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci usb_make_path(udev, remote->phys, sizeof(remote->phys)); 50362306a36Sopenharmony_ci strlcat(remote->phys, "/input0", sizeof(remote->phys)); 50462306a36Sopenharmony_ci memcpy(remote->keymap, keyspan_key_table, sizeof(remote->keymap)); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci input_dev->name = remote->name; 50762306a36Sopenharmony_ci input_dev->phys = remote->phys; 50862306a36Sopenharmony_ci usb_to_input_id(udev, &input_dev->id); 50962306a36Sopenharmony_ci input_dev->dev.parent = &interface->dev; 51062306a36Sopenharmony_ci input_dev->keycode = remote->keymap; 51162306a36Sopenharmony_ci input_dev->keycodesize = sizeof(unsigned short); 51262306a36Sopenharmony_ci input_dev->keycodemax = ARRAY_SIZE(remote->keymap); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci input_set_capability(input_dev, EV_MSC, MSC_SCAN); 51562306a36Sopenharmony_ci __set_bit(EV_KEY, input_dev->evbit); 51662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++) 51762306a36Sopenharmony_ci __set_bit(keyspan_key_table[i], input_dev->keybit); 51862306a36Sopenharmony_ci __clear_bit(KEY_RESERVED, input_dev->keybit); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci input_set_drvdata(input_dev, remote); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci input_dev->open = keyspan_open; 52362306a36Sopenharmony_ci input_dev->close = keyspan_close; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci /* 52662306a36Sopenharmony_ci * Initialize the URB to access the device. 52762306a36Sopenharmony_ci * The urb gets sent to the device in keyspan_open() 52862306a36Sopenharmony_ci */ 52962306a36Sopenharmony_ci usb_fill_int_urb(remote->irq_urb, 53062306a36Sopenharmony_ci remote->udev, 53162306a36Sopenharmony_ci usb_rcvintpipe(remote->udev, endpoint->bEndpointAddress), 53262306a36Sopenharmony_ci remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote, 53362306a36Sopenharmony_ci endpoint->bInterval); 53462306a36Sopenharmony_ci remote->irq_urb->transfer_dma = remote->in_dma; 53562306a36Sopenharmony_ci remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* we can register the device now, as it is ready */ 53862306a36Sopenharmony_ci error = input_register_device(remote->input); 53962306a36Sopenharmony_ci if (error) 54062306a36Sopenharmony_ci goto fail3; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci /* save our data pointer in this interface device */ 54362306a36Sopenharmony_ci usb_set_intfdata(interface, remote); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci return 0; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci fail3: usb_free_urb(remote->irq_urb); 54862306a36Sopenharmony_ci fail2: usb_free_coherent(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); 54962306a36Sopenharmony_ci fail1: kfree(remote); 55062306a36Sopenharmony_ci input_free_device(input_dev); 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci return error; 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci/* 55662306a36Sopenharmony_ci * Routine called when a device is disconnected from the USB. 55762306a36Sopenharmony_ci */ 55862306a36Sopenharmony_cistatic void keyspan_disconnect(struct usb_interface *interface) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci struct usb_keyspan *remote; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci remote = usb_get_intfdata(interface); 56362306a36Sopenharmony_ci usb_set_intfdata(interface, NULL); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (remote) { /* We have a valid driver structure so clean up everything we allocated. */ 56662306a36Sopenharmony_ci input_unregister_device(remote->input); 56762306a36Sopenharmony_ci usb_kill_urb(remote->irq_urb); 56862306a36Sopenharmony_ci usb_free_urb(remote->irq_urb); 56962306a36Sopenharmony_ci usb_free_coherent(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); 57062306a36Sopenharmony_ci kfree(remote); 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci/* 57562306a36Sopenharmony_ci * Standard driver set up sections 57662306a36Sopenharmony_ci */ 57762306a36Sopenharmony_cistatic struct usb_driver keyspan_driver = 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci .name = "keyspan_remote", 58062306a36Sopenharmony_ci .probe = keyspan_probe, 58162306a36Sopenharmony_ci .disconnect = keyspan_disconnect, 58262306a36Sopenharmony_ci .id_table = keyspan_table 58362306a36Sopenharmony_ci}; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cimodule_usb_driver(keyspan_driver); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, keyspan_table); 58862306a36Sopenharmony_ciMODULE_AUTHOR("Michael Downey <downey@zymeta.com>"); 58962306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver for the USB Keyspan remote control."); 59062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 591