static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude) { struct iforce *iforce = input_get_drvdata(dev); unsigned char data[3]; data[0] = 0x03; data[1] = magnitude >> 9; iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); data[0] = 0x04; data[1] = 0x01; iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); }
static void iforce_release(struct input_dev *dev) { struct iforce *iforce = input_get_drvdata(dev); int i; if (test_bit(EV_FF, dev->evbit)) { /* Check: no effects should be present in memory */ for (i = 0; i < dev->ff->max_effects; i++) { if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) { dev_warn(&dev->dev, "%s: Device still owns effects\n", __func__); break; } } /* Disable force feedback playback */ iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); } switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: usb_kill_urb(iforce->irq); /* The device was unplugged before the file * was released */ if (iforce->usbdev == NULL) { iforce_delete_device(iforce); kfree(iforce); } break; #endif } }
static int make_period_modifier(struct iforce* iforce, struct resource* mod_chunk, int no_alloc, __s16 magnitude, __s16 offset, u16 period, u16 phase) { unsigned char data[7]; period = TIME_SCALE(period); if (!no_alloc) { mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); data[1] = HI(mod_chunk->start); data[2] = HIFIX80(magnitude); data[3] = HIFIX80(offset); data[4] = HI(phase); data[5] = LO(period); data[6] = HI(period); iforce_send_packet(iforce, FF_CMD_PERIOD, data); return 0; }
static int make_magnitude_modifier(struct iforce* iforce, struct resource* mod_chunk, int no_alloc, __s16 level) { unsigned char data[3]; if (!no_alloc) { mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 2, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); data[1] = HI(mod_chunk->start); data[2] = HIFIX80(level); iforce_send_packet(iforce, FF_CMD_MAGNITUDE, data); iforce_dump_packet("magnitude: ", FF_CMD_MAGNITUDE, data); return 0; }
static void iforce_set_gain(struct input_dev *dev, u16 gain) { struct iforce *iforce = input_get_drvdata(dev); unsigned char data[3]; data[0] = gain >> 9; iforce_send_packet(iforce, FF_CMD_GAIN, data); }
/* Start or stop an effect */ int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value) { unsigned char data[3]; data[0] = LO(id); data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0; data[2] = LO(value); return iforce_send_packet(iforce, FF_CMD_PLAY, data); }
int iforce_get_id_packet(struct iforce *iforce, char *packet) { int status; switch (iforce->bus) { case IFORCE_USB: #ifdef CONFIG_JOYSTICK_IFORCE_USB iforce->cr.bRequest = packet[0]; iforce->ctrl->dev = iforce->usbdev; status = usb_submit_urb(iforce->ctrl, GFP_ATOMIC); if (status) { err("usb_submit_urb failed %d", status); return -1; } wait_event_interruptible_timeout(iforce->wait, iforce->ctrl->status != -EINPROGRESS, HZ); if (iforce->ctrl->status) { dbg("iforce->ctrl->status = %d", iforce->ctrl->status); usb_unlink_urb(iforce->ctrl); return -1; } #else dbg("iforce_get_id_packet: iforce->bus = USB!"); #endif break; case IFORCE_232: #ifdef CONFIG_JOYSTICK_IFORCE_232 iforce->expect_packet = FF_CMD_QUERY; iforce_send_packet(iforce, FF_CMD_QUERY, packet); wait_event_interruptible_timeout(iforce->wait, !iforce->expect_packet, HZ); if (iforce->expect_packet) { iforce->expect_packet = 0; return -1; } #else err("iforce_get_id_packet: iforce->bus = SERIO!"); #endif break; default: err("iforce_get_id_packet: iforce->bus = %d", iforce->bus); break; } return -(iforce->edata[0] != packet[0]); }
/* Start or stop an effect */ int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value) { unsigned char data[3]; printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value); data[0] = LO(id); data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0; data[2] = LO(value); return iforce_send_packet(iforce, FF_CMD_PLAY, data); }
static int iforce_open(struct input_dev *dev) { struct iforce *iforce = input_get_drvdata(dev); switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: iforce->irq->dev = iforce->usbdev; if (usb_submit_urb(iforce->irq, GFP_KERNEL)) return -EIO; break; #endif } if (test_bit(EV_FF, dev->evbit)) { /* Enable force feedback */ iforce_send_packet(iforce, FF_CMD_ENABLE, "\004"); } return 0; }
static int make_condition_modifier(struct iforce* iforce, struct resource* mod_chunk, int no_alloc, __u16 rsat, __u16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center) { unsigned char data[10]; if (!no_alloc) { mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 8, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); data[1] = HI(mod_chunk->start); data[2] = (100 * rk) >> 15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */ data[3] = (100 * lk) >> 15; /* This code is incorrect on cpus lacking arith shift */ center = (500 * center) >> 15; data[4] = LO(center); data[5] = HI(center); db = (1000 * db) >> 16; data[6] = LO(db); data[7] = HI(db); data[8] = (100 * rsat) >> 16; data[9] = (100 * lsat) >> 16; iforce_send_packet(iforce, FF_CMD_CONDITION, data); iforce_dump_packet("condition", FF_CMD_CONDITION, data); return 0; }
static int make_condition_modifier(struct iforce* iforce, struct resource* mod_chunk, int no_alloc, __u16 rsat, __u16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center) { unsigned char data[10]; if (!no_alloc) { mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 8, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); data[1] = HI(mod_chunk->start); data[2] = (100 * rk) >> 15; data[3] = (100 * lk) >> 15; center = (500 * center) >> 15; data[4] = LO(center); data[5] = HI(center); db = (1000 * db) >> 16; data[6] = LO(db); data[7] = HI(db); data[8] = (100 * rsat) >> 16; data[9] = (100 * lsat) >> 16; iforce_send_packet(iforce, FF_CMD_CONDITION, data); iforce_dump_packet("condition", FF_CMD_CONDITION, data); return 0; }
static void iforce_close(struct input_dev *dev) { struct iforce *iforce = input_get_drvdata(dev); int i; if (test_bit(EV_FF, dev->evbit)) { /* Check: no effects should be present in memory */ for (i = 0; i < dev->ff->max_effects; i++) { if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) { dev_warn(&dev->dev, "%s: Device still owns effects\n", __func__); break; } } /* Disable force feedback playback */ iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); /* Wait for the command to complete */ wait_event_interruptible(iforce->wait, !test_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)); } switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: usb_kill_urb(iforce->irq); usb_kill_urb(iforce->out); usb_kill_urb(iforce->ctrl); break; #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 case IFORCE_232: //TODO: Wait for the last packets to be sent break; #endif } }
static int make_envelope_modifier(struct iforce* iforce, struct resource* mod_chunk, int no_alloc, u16 attack_duration, __s16 initial_level, u16 fade_duration, __s16 final_level) { unsigned char data[8]; attack_duration = TIME_SCALE(attack_duration); fade_duration = TIME_SCALE(fade_duration); if (!no_alloc) { mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { mutex_unlock(&iforce->mem_mutex); return -ENOSPC; } mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); data[1] = HI(mod_chunk->start); data[2] = LO(attack_duration); data[3] = HI(attack_duration); data[4] = HI(initial_level); data[5] = LO(fade_duration); data[6] = HI(fade_duration); data[7] = HI(final_level); iforce_send_packet(iforce, FF_CMD_ENVELOPE, data); return 0; }