static int uhid_dev_create(struct uhid_device *uhid, const struct uhid_event *ev) { struct hid_device *hid; int ret; if (uhid->running) return -EALREADY; uhid->rd_size = ev->u.create.rd_size; if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) return -EINVAL; uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL); if (!uhid->rd_data) return -ENOMEM; if (copy_from_user(uhid->rd_data, ev->u.create.rd_data, uhid->rd_size)) { ret = -EFAULT; goto err_free; } hid = hid_allocate_device(); if (IS_ERR(hid)) { ret = PTR_ERR(hid); goto err_free; } strncpy(hid->name, ev->u.create.name, 127); hid->name[127] = 0; strncpy(hid->phys, ev->u.create.phys, 63); hid->phys[63] = 0; strncpy(hid->uniq, ev->u.create.uniq, 63); hid->uniq[63] = 0; hid->ll_driver = &uhid_hid_driver; hid->hid_get_raw_report = uhid_hid_get_raw; hid->hid_output_raw_report = uhid_hid_output_raw; hid->bus = ev->u.create.bus; hid->vendor = ev->u.create.vendor; hid->product = ev->u.create.product; hid->version = ev->u.create.version; hid->country = ev->u.create.country; hid->driver_data = uhid; hid->dev.parent = uhid_misc.this_device; uhid->hid = hid; uhid->running = true; ret = hid_add_device(hid); if (ret) { hid_err(hid, "Cannot register HID device\n"); goto err_hid; } return 0; err_hid: hid_destroy_device(hid); uhid->hid = NULL; uhid->running = false; err_free: kfree(uhid->rd_data); return ret; }
static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) { /* Called in delayed work context */ struct hid_device *djrcv_hdev = djrcv_dev->hdev; struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent); struct usb_device *usbdev = interface_to_usbdev(intf); struct hid_device *dj_hiddev; struct dj_device *dj_dev; /* Device index goes from 1 to 6, we need 3 bytes to store the * semicolon, the index, and a null terminator */ unsigned char tmpstr[3]; if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & SPFUNCTION_DEVICE_LIST_EMPTY) { dbg_hid("%s: device list is empty\n", __func__); return; } if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { /* The device is already known. No need to reallocate it. */ dbg_hid("%s: device is already known\n", __func__); return; } dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", __func__); return; } dj_hiddev->ll_driver = &logi_dj_ll_driver; dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report; dj_hiddev->dev.parent = &djrcv_hdev->dev; dj_hiddev->bus = BUS_USB; dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor); dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct); snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), "Logitech Unifying Device. Wireless PID:%02x%02x", dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB], dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]); usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys)); snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys)); dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL); if (!dj_dev) { dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n", __func__); goto dj_device_allocate_fail; } dj_dev->reports_supported = le32_to_cpu( dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]); dj_dev->hdev = dj_hiddev; dj_dev->dj_receiver_dev = djrcv_dev; dj_dev->device_index = dj_report->device_index; dj_hiddev->driver_data = dj_dev; djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev; if (hid_add_device(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n", __func__); goto hid_add_device_fail; } return; hid_add_device_fail: djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL; kfree(dj_dev); dj_device_allocate_fail: hid_destroy_device(dj_hiddev); }
static int bthid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret; char *name; struct bthid_ctrl *p_ctrl; struct bthid_device *p_dev = file->private_data; struct bthid_di di; #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "######## bthid_ioctl: cmd = %d ########\n", cmd); #else ; #endif if (p_dev == NULL) { return -EINVAL; } if (cmd == BTHID_IOCTL_RPT_NAME) { name = kzalloc(BTHID_DEV_NAME_LEN, GFP_KERNEL); if (name == NULL) return -ENOMEM; if (copy_from_user(name, (void __user *)arg, BTHID_DEV_NAME_LEN)) { kfree(name); return -EFAULT; } #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "%s: name=%s\n", __func__, name); #else ; #endif if (!p_dev->hid) { p_dev->hid = hid_allocate_device(); if (p_dev->hid == NULL) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "Oops: Failed to allocation HID device.\n"); #else ; #endif kfree(name); return -ENOMEM; } } strncpy(p_dev->hid->name, name, 128); kfree(name); } else if (cmd == BTHID_IOCTL_RPT_DI) { if (copy_from_user(&di, (void __user *) arg, sizeof(struct bthid_di)) != 0) { return -EFAULT; } #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "%s: vendor=0x%04x, product=0x%04x, version=0x%04x, country=0x%02x\n", __func__, di.vendor_id, di.product_id, di.version, di.ctry_code); #else ; #endif if (!p_dev->hid) { p_dev->hid = hid_allocate_device(); if (p_dev->hid == NULL) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "Oops: Failed to allocation HID device.\n"); #else ; #endif return -ENOMEM; } } p_dev->hid->vendor = di.vendor_id; p_dev->hid->product = di.product_id; p_dev->hid->version = di.version; p_dev->hid->country = di.ctry_code; } else if (cmd == BTHID_IOCTL_RPT_DSCP) { p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL); if (p_ctrl == NULL) { return -ENOMEM; } if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0) { kfree(p_ctrl); return -EFAULT; } if (p_ctrl->size <= 0) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "Oops: Invalid BT HID report descriptor size %d\n", p_ctrl->size); #else ; #endif kfree(p_ctrl); return -EINVAL; } if (!p_dev->hid) { p_dev->hid = hid_allocate_device(); if (p_dev->hid == NULL) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "Oops: Failed to allocation HID device.\n"); #else ; #endif kfree(p_ctrl); return -ENOMEM; } } if (p_dev->hid->vendor == 0x04E8 && p_dev->hid->product == 0x7021) { strcpy(p_dev->hid->name, "Vendor_04E8_Product_7021"); p_dev->hid->name[strlen("Vendor_04E8_Product_7021")] = '\0'; } else { strcpy(p_dev->hid->name, "Broadcom Bluetooth HID"); p_dev->hid->vendor = 0; p_dev->hid->product = 0; p_dev->hid->version = 0; p_dev->hid->country = 0; p_dev->hid->name[strlen("Broadcom Bluetooth HID")] = '\0'; } p_dev->hid->bus = BUS_BLUETOOTH; p_dev->hid->ll_driver = &bthid_ll_driver; p_dev->hid->driver_data = p_ctrl; ret = hid_add_device(p_dev->hid); #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "hid_add_device: ret = %d, hid->status = %d\n", ret, p_dev->hid->status); #else ; #endif if (ret != 0) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "Oops: Failed to add HID device"); #else ; #endif kfree(p_ctrl); hid_destroy_device(p_dev->hid); p_dev->hid = NULL; return -EINVAL; } p_dev->hid->claimed |= HID_CLAIMED_INPUT; if (p_dev->hid->status != (HID_STAT_ADDED | HID_STAT_PARSED)) { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "Oops: Failed to process HID report descriptor"); #else ; #endif return -EINVAL; } p_dev->dscp_set = 1; } else { #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "Invlid ioctl value"); #else ; #endif return -EINVAL; } #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "######## bthid_ioctl: done ########\n"); #else ; #endif return 0; }
static long bthid_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) //static int bthid_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret; struct bthid_ctrl *p_ctrl; struct bthid_device *p_dev = file->private_data; printk("######## bthid_unlocked_ioctl: cmd = %d ########\n", cmd); if (cmd != BTHID_IOCTL_HID_INFO || p_dev == NULL) { return -EINVAL; } p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL); if (p_ctrl == NULL) { return -ENOMEM; } if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0) { kfree(p_ctrl); return -EFAULT; } printk("bthid: name = [%s], VID/PID = %04x/%04x, version = 0x%04x, country = 0x%02x\n", p_ctrl->dev_name, p_ctrl->vendor_id, p_ctrl->product_id, p_ctrl->version, p_ctrl->ctry_code); if (p_ctrl->dscp_len <= 0) { printk("Oops: Invalid BT HID report descriptor size %d\n", p_ctrl->dscp_len); kfree(p_ctrl); return -EINVAL; } p_dev->hid = hid_allocate_device(); if (p_dev->hid == NULL) { printk("Oops: Failed to allocation HID device.\n"); kfree(p_ctrl); return -ENOMEM; } p_dev->hid->bus = BUS_BLUETOOTH; p_dev->hid->vendor = p_ctrl->vendor_id; p_dev->hid->product = p_ctrl->product_id; p_dev->hid->version = p_ctrl->version; p_dev->hid->country = p_ctrl->ctry_code; p_dev->hid->ll_driver = &bthid_ll_driver; p_dev->hid->driver_data = p_ctrl; // strcpy(p_dev->hid->name, "Broadcom Bluetooth HID"); strncpy(p_dev->hid->name, p_ctrl->dev_name, BTHID_MAX_DEV_NAME_LEN); ret = hid_add_device(p_dev->hid); printk("hid_add_device: ret = %d, hid->status = %d\n", ret, p_dev->hid->status); if (ret != 0) { printk("Oops: Failed to add HID device"); kfree(p_ctrl); hid_destroy_device(p_dev->hid); p_dev->hid = NULL; return -EINVAL; } p_dev->hid->claimed |= HID_CLAIMED_INPUT; if (p_dev->hid->status != (HID_STAT_ADDED | HID_STAT_PARSED)) { printk("Oops: Failed to process HID report descriptor"); return -EINVAL; } p_dev->dscp_set = 1; printk("######## bthid_unlocked_ioctl: done ########\n"); return 0; }
static int mousevsc_probe(struct hv_device *device, const struct hv_vmbus_device_id *dev_id) { int ret; struct mousevsc_dev *input_dev; struct hid_device *hid_dev; input_dev = mousevsc_alloc_device(device); if (!input_dev) return -ENOMEM; ret = vmbus_open(device->channel, INPUTVSC_SEND_RING_BUFFER_SIZE, INPUTVSC_RECV_RING_BUFFER_SIZE, NULL, 0, mousevsc_on_channel_callback, device ); if (ret) goto probe_err0; ret = mousevsc_connect_to_vsp(device); if (ret) goto probe_err1; /* workaround SA-167 */ if (input_dev->report_desc[14] == 0x25) input_dev->report_desc[14] = 0x29; hid_dev = hid_allocate_device(); if (IS_ERR(hid_dev)) { ret = PTR_ERR(hid_dev); goto probe_err1; } hid_dev->ll_driver = &mousevsc_ll_driver; hid_dev->driver = &mousevsc_hid_driver; hid_dev->bus = BUS_VIRTUAL; hid_dev->vendor = input_dev->hid_dev_info.vendor; hid_dev->product = input_dev->hid_dev_info.product; hid_dev->version = input_dev->hid_dev_info.version; input_dev->hid_device = hid_dev; sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); hid_set_drvdata(hid_dev, device); ret = hid_add_device(hid_dev); if (ret) goto probe_err1; ret = hid_parse(hid_dev); if (ret) { hid_err(hid_dev, "parse failed\n"); goto probe_err2; } ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); if (ret) { hid_err(hid_dev, "hw start failed\n"); goto probe_err2; } input_dev->connected = true; input_dev->init_complete = true; return ret; probe_err2: hid_destroy_device(hid_dev); probe_err1: vmbus_close(device->channel); probe_err0: mousevsc_free_device(input_dev); return ret; }
static int bthid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret; struct bthid_ctrl *p_ctrl; struct bthid_device *p_dev = file->private_data; printk("######## bthid_ioctl: cmd = %d ########\n", cmd); if (cmd != BTHID_IOCTL_RPT_DSCP || p_dev == NULL) { return -EINVAL; } p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL); if (p_ctrl == NULL) { return -ENOMEM; } if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0) { kfree(p_ctrl); return -EFAULT; } if (p_ctrl->size <= 0) { printk("Oops: Invalid BT HID report descriptor size %d\n", p_ctrl->size); kfree(p_ctrl); return -EINVAL; } p_dev->hid = hid_allocate_device(); if (p_dev->hid == NULL) { printk("Oops: Failed to allocation HID device.\n"); kfree(p_ctrl); return -ENOMEM; } p_dev->hid->bus = BUS_BLUETOOTH; p_dev->hid->vendor = 0; p_dev->hid->product = 0; p_dev->hid->version = 0; p_dev->hid->country = 0; p_dev->hid->ll_driver = &bthid_ll_driver; p_dev->hid->driver_data = p_ctrl; strcpy(p_dev->hid->name, "Broadcom Bluetooth HID"); ret = hid_add_device(p_dev->hid); printk("hid_add_device: ret = %d, hid->status = %d\n", ret, p_dev->hid->status); if (ret != 0) { printk("Oops: Failed to add HID device"); kfree(p_ctrl); hid_destroy_device(p_dev->hid); p_dev->hid = NULL; return -EINVAL; } p_dev->hid->claimed |= HID_CLAIMED_INPUT; if (p_dev->hid->status != (HID_STAT_ADDED | HID_STAT_PARSED)) { printk("Oops: Failed to process HID report descriptor"); return -EINVAL; } p_dev->dscp_set = 1; printk("######## bthid_ioctl: done ########\n"); return 0; }
static long bthid_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #endif { struct bthid_ctrl *p_ctrl; struct bthid_device *p_dev = file->private_data; printk("######## bthid_ioctl: cmd = %d ########\n", cmd); if (cmd != BTHID_IOCTL_RPT_DSCP || p_dev == NULL) { return -EINVAL; } p_ctrl = kmalloc(sizeof(struct bthid_ctrl), GFP_KERNEL); if (p_ctrl == NULL) { return -ENOMEM; } if (copy_from_user(p_ctrl, (void __user *) arg, sizeof(struct bthid_ctrl)) != 0) { kfree(p_ctrl); return -EFAULT; } if (p_ctrl->size <= 0) { printk("Oops: Invalid BT HID report descriptor size %d\n", p_ctrl->size); kfree(p_ctrl); return -EINVAL; } p_dev->hid = hid_allocate_device(); if (p_dev->hid == NULL) { printk("Oops: Failed to allocation HID device.\n"); kfree(p_ctrl); return -ENOMEM; } p_dev->hid->bus = BUS_BLUETOOTH; p_dev->hid->vendor = 0; p_dev->hid->product = 0; p_dev->hid->version = 0; p_dev->hid->country = 0; p_dev->hid->ll_driver = &bthid_ll_driver; p_dev->hid->driver_data = p_ctrl; strcpy(p_dev->hid->name, "Broadcom Bluetooth HID"); if (hid_add_device(p_dev->hid) != 0) { printk("Oops: Failed to add HID device\n"); kfree(p_ctrl); hid_destroy_device(p_dev->hid); p_dev->hid = NULL; return -EINVAL; } // TBD: don't know whether it is required if (hidinput_connect(p_dev->hid, 0) == 0) { printk("bthid_ioctl: HID Interface Claimed...\n"); p_dev->hid->claimed |= HID_CLAIMED_INPUT; } p_dev->dscp_set = 1; printk("######## bthid_ioctl: done ########\n"); return 0; }