⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iforce.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
 */static int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect){	u8 wave_code;	int core_id = effect->id;	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);	int err = 0;	err = make_period_modifier(iforce, mod1_chunk,		effect->u.periodic.magnitude, effect->u.periodic.offset,		effect->u.periodic.period, effect->u.periodic.phase);	if (err) return err;	set_bit(FF_MOD1_IS_USED, core_effect->flags);	err = make_shape_modifier(iforce, mod2_chunk,		effect->u.periodic.shape.attack_length,		effect->u.periodic.shape.attack_level,		effect->u.periodic.shape.fade_length,		effect->u.periodic.shape.fade_level);	if (err) return err;	set_bit(FF_MOD2_IS_USED, core_effect->flags);	switch (effect->u.periodic.waveform) {		case FF_SQUARE:		wave_code = 0x20; break;		case FF_TRIANGLE:	wave_code = 0x21; break;		case FF_SINE:		wave_code = 0x22; break;		case FF_SAW_UP:		wave_code = 0x23; break;		case FF_SAW_DOWN:	wave_code = 0x24; break;		default:		wave_code = 0x20; break;	}	err = make_core(iforce, effect->id,		mod1_chunk->start,		mod2_chunk->start,		wave_code,		0x20,		effect->replay.length,		effect->replay.delay,		effect->trigger.button,		effect->trigger.interval,		effect->u.periodic.direction);	return err;}/* * Upload a constant force effect */static int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect){	int core_id = effect->id;	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;	struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);	struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);	int err = 0;	printk(KERN_DEBUG "iforce.c: make constant effect\n");	err = make_magnitude_modifier(iforce, mod1_chunk, effect->u.constant.level);	if (err) return err;	set_bit(FF_MOD1_IS_USED, core_effect->flags);	err = make_shape_modifier(iforce, mod2_chunk,		effect->u.constant.shape.attack_length,		effect->u.constant.shape.attack_level,		effect->u.constant.shape.fade_length,		effect->u.constant.shape.fade_level);	if (err) return err;	set_bit(FF_MOD2_IS_USED, core_effect->flags);	err = make_core(iforce, effect->id,		mod1_chunk->start,		mod2_chunk->start,		0x00,		0x20,		effect->replay.length,		effect->replay.delay,		effect->trigger.button,		effect->trigger.interval,		effect->u.constant.direction);	return err;}/* * Upload an interactive effect. Those are for example friction, inertia, springs... */static int iforce_upload_interactive(struct iforce* iforce, struct ff_effect* effect){	int core_id = effect->id;	struct iforce_core_effect* core_effect = iforce->core_effects + core_id;	struct resource* mod_chunk = &(core_effect->mod1_chunk);	u8 type, axes;	u16 mod1, mod2, direction;	int err = 0;	printk(KERN_DEBUG "iforce.c: make interactive effect\n");	switch (effect->type) {		case FF_SPRING:		type = 0x40; break;		case FF_FRICTION:	type = 0x41; break;		default: return -1;	}	err = make_interactive_modifier(iforce, mod_chunk,		effect->u.interactive.right_saturation,		effect->u.interactive.left_saturation,		effect->u.interactive.right_coeff,		effect->u.interactive.left_coeff,		effect->u.interactive.deadband,		effect->u.interactive.center);	if (err) return err;	set_bit(FF_MOD1_IS_USED, core_effect->flags);	switch ((test_bit(ABS_X, &effect->u.interactive.axis) ||		test_bit(ABS_WHEEL, &effect->u.interactive.axis)) |		(!!test_bit(ABS_Y, &effect->u.interactive.axis) << 1)) {		case 0: /* Only one axis, choose orientation */			mod1 = mod_chunk->start;			mod2 = 0xffff;			direction = effect->u.interactive.direction;			axes = 0x20;			break;		case 1:	/* Only X axis */			mod1 = mod_chunk->start;			mod2 = 0xffff;			direction = 0x5a00;			axes = 0x40;			break;		case 2: /* Only Y axis */			mod1 = 0xffff;			mod2 = mod_chunk->start;			direction = 0xb400;			axes = 0x80;			break;		case 3:	/* Both X and Y axes */			/* TODO: same setting for both axes is not mandatory */			mod1 = mod_chunk->start;			mod2 = mod_chunk->start;			direction = 0x6000;			axes = 0xc0;			break;		default:			return -1;	}	err = make_core(iforce, effect->id,		mod1, mod2,		type, axes,		effect->replay.length, effect->replay.delay,		effect->trigger.button, effect->trigger.interval,		direction);	return err;}/* * Function called when an ioctl is performed on the event dev entry. * It uploads an effect to the device */static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect){	struct iforce* iforce = (struct iforce*)(dev->private);	int id;	printk(KERN_DEBUG "iforce.c: upload effect\n");/* * Get a free id */	for (id=0; id < FF_EFFECTS_MAX; ++id)		if (!test_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;	if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)		return -ENOMEM;	effect->id = id;	set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags);/* * Upload the effect */	switch (effect->type) {		case FF_PERIODIC:			return iforce_upload_periodic(iforce, effect);		case FF_CONSTANT:			return iforce_upload_constant(iforce, effect);		case FF_SPRING:		case FF_FRICTION:			return iforce_upload_interactive(iforce, effect);		default:			return -1;	}}/* * Erases an effect: it frees the effect id and mark as unused the memory * allocated for the parameters */static int iforce_erase_effect(struct input_dev *dev, int effect_id){	struct iforce* iforce = (struct iforce*)(dev->private);	int err = 0;	struct iforce_core_effect* core_effect;	printk(KERN_DEBUG "iforce.c: erase effect %d\n", effect_id);	if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)		return -EINVAL;	core_effect = iforce->core_effects + effect_id;	if (test_bit(FF_MOD1_IS_USED, core_effect->flags))		err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));	if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))		err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));	/*TODO: remember to change that if more FF_MOD* bits are added */	core_effect->flags[0] = 0;	return err;}static int iforce_init_device(struct iforce *iforce){	unsigned char c[] = "CEOV";	int i;	init_waitqueue_head(&iforce->wait);	iforce->dev.ff_effects_max = 10;/* * Input device fields. */	iforce->dev.idbus = BUS_USB;	iforce->dev.private = iforce;	iforce->dev.name = iforce->name;	iforce->dev.open = iforce_open;	iforce->dev.close = iforce_close;	iforce->dev.event = iforce_input_event;	iforce->dev.upload_effect = iforce_upload_effect;	iforce->dev.erase_effect = iforce_erase_effect;/* * On-device memory allocation. */	iforce->device_memory.name = "I-Force device effect memory";	iforce->device_memory.start = 0;	iforce->device_memory.end = 200;	iforce->device_memory.flags = IORESOURCE_MEM;	iforce->device_memory.parent = NULL;	iforce->device_memory.child = NULL;	iforce->device_memory.sibling = NULL;/* * Wait until device ready - until it sends its first response. */	for (i = 0; i < 20; i++)		if (!get_id_packet(iforce, "O"))			break;	if (i == 20) { /* 5 seconds */		printk(KERN_ERR "iforce.c: Timeout waiting for response from device.\n");		iforce_close(&iforce->dev);		return -1;	}/* * Get device info. */	if (!get_id_packet(iforce, "M"))		iforce->dev.idvendor = (iforce->edata[2] << 8) | iforce->edata[1];	if (!get_id_packet(iforce, "P"))		iforce->dev.idproduct = (iforce->edata[2] << 8) | iforce->edata[1];	if (!get_id_packet(iforce, "B"))		iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];	if (!get_id_packet(iforce, "N"))		iforce->dev.ff_effects_max = iforce->edata[1];/* * Display additional info. */	for (i = 0; c[i]; i++)		if (!get_id_packet(iforce, c + i))			dump_packet("info", iforce->ecmd, iforce->edata);/* * Disable spring, enable force feedback. * FIXME: We should use iforce_set_autocenter() et al here. */	send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");	send_packet(iforce, FF_CMD_ENABLE, "\004");/* * Find appropriate device entry */	for (i = 0; iforce_device[i].idvendor; i++)		if (iforce_device[i].idvendor == iforce->dev.idvendor &&		    iforce_device[i].idproduct == iforce->dev.idproduct)			break;	iforce->type = iforce_device + i;	sprintf(iforce->name, iforce->type->name,		iforce->dev.idproduct, iforce->dev.idvendor);/* * Set input device bitfields and ranges. */	iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF);	for (i = 0; iforce->type->btn[i] >= 0; i++) {		signed short t = iforce->type->btn[i];		set_bit(t, iforce->dev.keybit);		if (t != BTN_DEAD)			set_bit(FF_BTN(t), iforce->dev.ffbit);	}	for (i = 0; iforce->type->abs[i] >= 0; i++) {		signed short t = iforce->type->abs[i];		set_bit(t, iforce->dev.absbit);		switch (t) {			case ABS_X:			case ABS_Y:			case ABS_WHEEL:				iforce->dev.absmax[t] =  1920;				iforce->dev.absmin[t] = -1920;				iforce->dev.absflat[t] = 128;				iforce->dev.absfuzz[t] = 16;				set_bit(FF_ABS(t), iforce->dev.ffbit);				break;			case ABS_THROTTLE:			case ABS_GAS:			case ABS_BRAKE:				iforce->dev.absmax[t] = 255;				iforce->dev.absmin[t] = 0;				break;			case ABS_HAT0X:			case ABS_HAT0Y:				iforce->dev.absmax[t] =  1;				iforce->dev.absmin[t] = -1;				break;		}	}	for (i = 0; iforce->type->ff[i] >= 0; i++)		set_bit(iforce->type->ff[i], iforce->dev.ffbit);/* * Register input device. */	input_register_device(&iforce->dev);	return 0;}#ifdef IFORCE_USBstatic void iforce_usb_irq(struct urb *urb){	struct iforce *iforce = urb->context;	if (urb->status) return;	iforce_process_packet(iforce,		(iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1);}static void iforce_usb_out(struct urb *urb){	struct iforce *iforce = urb->context;	if (urb->status) return;	if (waitqueue_active(&iforce->wait))		wake_up(&iforce->wait);}static void iforce_usb_ctrl(struct urb *urb){	struct iforce *iforce = urb->context;	if (urb->status) return;	iforce->ecmd = 0xff00 | urb->actual_length;	if (waitqueue_active(&iforce->wait))		wake_up(&iforce->wait);}static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum,				const struct usb_device_id *id){	struct usb_endpoint_descriptor *epirq, *epout;	struct iforce *iforce;	epirq = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;	epout = dev->config[0].interface[ifnum].altsetting[0].endpoint + 1;	if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL))) return NULL;	memset(iforce, 0, sizeof(struct iforce));	iforce->bus = IFORCE_USB;	iforce->usbdev = dev;	iforce->dr.requesttype = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;	iforce->dr.index = 0;	iforce->dr.length = 16;	FILL_INT_URB(&iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),			iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);	FILL_BULK_URB(&iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),			iforce + 1, 32, iforce_usb_out, iforce);	FILL_CONTROL_URB(&iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),			(void*) &iforce->dr, iforce->edata, 16, iforce_usb_ctrl, iforce);	if (iforce_init_device(iforce)) {		kfree(iforce);		return NULL;	}	printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on usb%d:%d.%d\n",		iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,		iforce->device_memory.end, dev->bus->busnum, dev->devnum, ifnum);	return iforce;}static void iforce_usb_disconnect(struct usb_device *dev, void *ptr){	struct iforce *iforce = ptr;	usb_unlink_urb(&iforce->irq);	input_unregister_device(&iforce->dev);	kfree(iforce);}static struct usb_device_id iforce_usb_ids [] = {	{ USB_DEVICE(0x046d, 0xc281) },		/* Logitech WingMan Force */	{ USB_DEVICE(0x046d, 0xc291) },		/* Logitech WingMan Formula Force */	{ USB_DEVICE(0x05ef, 0x020a) },		/* AVB Top Shot Pegasus */	{ USB_DEVICE(0x05ef, 0x8884) },		/* AVB Mag Turbo Force */	{ USB_DEVICE(0x06f8, 0x0001) },		/* Guillemot Race Leader Force Feedback */	{ }					/* Terminating entry */};MODULE_DEVICE_TABLE (usb, iforce_usb_ids);static struct usb_driver iforce_usb_driver = {	name:		"iforce",	probe:		iforce_usb_probe,	disconnect:	iforce_usb_disconnect,	id_table:	iforce_usb_ids,};#endif#ifdef IFORCE_232static void iforce_serio_irq(struct serio *serio, unsigned char data, unsigned int flags){	struct iforce* iforce = serio->private;	if (!iforce->pkt) {		if (data != 0x2b) {			return;		}		iforce->pkt = 1;		return;	}	if (!iforce->id) {		if (data > 3 && data != 0xff) {			iforce->pkt = 0;			return;		}		iforce->id = data;		return;	}	if (!iforce->len) {		if (data > IFORCE_MAX_LENGTH) {			iforce->pkt = 0;			iforce->id = 0;			return;		}		iforce->len = data;		return;	}	if (iforce->idx < iforce->len) {		iforce->csum += iforce->data[iforce->idx++] = data;		return;	}	if (iforce->idx == iforce->len) {		iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data);		iforce->pkt = 0;		iforce->id  = 0;		iforce->len = 0;		iforce->idx = 0;		iforce->csum = 0;	}}static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev){	struct iforce *iforce;	if (serio->type != (SERIO_RS232 | SERIO_IFORCE))		return;	if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return;	memset(iforce, 0, sizeof(struct iforce));	iforce->bus = IFORCE_232;	iforce->serio = serio;	serio->private = iforce;	if (serio_open(serio, dev)) {		kfree(iforce);		return;	}	if (iforce_init_device(iforce)) {		serio_close(serio);		kfree(iforce);		return;	}	printk(KERN_INFO "input%d: %s [%d effects, %ld bytes memory] on serio%d\n",		iforce->dev.number, iforce->dev.name, iforce->dev.ff_effects_max,		iforce->device_memory.end, serio->number);}static void iforce_serio_disconnect(struct serio *serio){	struct iforce* iforce = serio->private;	input_unregister_device(&iforce->dev);	serio_close(serio);	kfree(iforce);}static struct serio_dev iforce_serio_dev = {	interrupt:	iforce_serio_irq,	connect:	iforce_serio_connect,	disconnect:	iforce_serio_disconnect,};#endifstatic int __init iforce_init(void){#ifdef IFORCE_USB	usb_register(&iforce_usb_driver);#endif#ifdef IFORCE_232	serio_register_device(&iforce_serio_dev);#endif	return 0;}static void __exit iforce_exit(void){#ifdef IFORCE_USB	usb_deregister(&iforce_usb_driver);#endif#ifdef IFORCE_232	serio_unregister_device(&iforce_serio_dev);#endif}module_init(iforce_init);module_exit(iforce_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -