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

📄 gtco.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			break;		}	}}/*   INPUT DRIVER Routines                               *//* * Called when opening the input device.  This will submit the URB to * the usb system so we start getting reports */static int gtco_input_open(struct input_dev *inputdev){	struct gtco *device = input_get_drvdata(inputdev);	device->urbinfo->dev = device->usbdev;	if (usb_submit_urb(device->urbinfo, GFP_KERNEL))		return -EIO;	return 0;}/* * Called when closing the input device.  This will unlink the URB */static void gtco_input_close(struct input_dev *inputdev){	struct gtco *device = input_get_drvdata(inputdev);	usb_kill_urb(device->urbinfo);}/* *  Setup input device capabilities.  Tell the input system what this *  device is capable of generating. * *  This information is based on what is read from the HID report and *  placed in the struct gtco structure * */static void gtco_setup_caps(struct input_dev *inputdev){	struct gtco *device = input_get_drvdata(inputdev);	/* Which events */	inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) |		BIT_MASK(EV_MSC);	/* Misc event menu block */	inputdev->mscbit[0] = BIT_MASK(MSC_SCAN) | BIT_MASK(MSC_SERIAL) |		BIT_MASK(MSC_RAW);	/* Absolute values based on HID report info */	input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X,			     0, 0);	input_set_abs_params(inputdev, ABS_Y, device->min_Y, device->max_Y,			     0, 0);	/* Proximity */	input_set_abs_params(inputdev, ABS_DISTANCE, 0, 1, 0, 0);	/* Tilt & pressure */	input_set_abs_params(inputdev, ABS_TILT_X, device->mintilt_X,			     device->maxtilt_X, 0, 0);	input_set_abs_params(inputdev, ABS_TILT_Y, device->mintilt_Y,			     device->maxtilt_Y, 0, 0);	input_set_abs_params(inputdev, ABS_PRESSURE, device->minpressure,			     device->maxpressure, 0, 0);	/* Transducer */	input_set_abs_params(inputdev, ABS_MISC, 0, 0xFF, 0, 0);}/*   USB Routines  *//* * URB callback routine.  Called when we get IRQ reports from the *  digitizer. * *  This bridges the USB and input device worlds.  It generates events *  on the input device based on the USB reports. */static void gtco_urb_callback(struct urb *urbinfo){	struct gtco *device = urbinfo->context;	struct input_dev  *inputdev;	int               rc;	u32               val = 0;	s8                valsigned = 0;	char              le_buffer[2];	inputdev = device->inputdevice;	/* Was callback OK? */	if (urbinfo->status == -ECONNRESET ||	    urbinfo->status == -ENOENT ||	    urbinfo->status == -ESHUTDOWN) {		/* Shutdown is occurring. Return and don't queue up any more */		return;	}	if (urbinfo->status != 0) {		/*		 * Some unknown error.  Hopefully temporary. Just go and		 * requeue an URB		 */		goto resubmit;	}	/*	 * Good URB, now process	 */	/* PID dependent when we interpret the report */	if (inputdev->id.product == PID_1000 ||	    inputdev->id.product == PID_1001 ||	    inputdev->id.product == PID_1002) {		/*		 * Switch on the report ID		 * Conveniently, the reports have more information, the higher		 * the report number.  We can just fall through the case		 * statements if we start with the highest number report		 */		switch (device->buffer[0]) {		case 5:			/* Pressure is 9 bits */			val = ((u16)(device->buffer[8]) << 1);			val |= (u16)(device->buffer[7] >> 7);			input_report_abs(inputdev, ABS_PRESSURE,					 device->buffer[8]);			/* Mask out the Y tilt value used for pressure */			device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);			/* Fall thru */		case 4:			/* Tilt */			/* Sign extend these 7 bit numbers.  */			if (device->buffer[6] & 0x40)				device->buffer[6] |= 0x80;			if (device->buffer[7] & 0x40)				device->buffer[7] |= 0x80;			valsigned = (device->buffer[6]);			input_report_abs(inputdev, ABS_TILT_X, (s32)valsigned);			valsigned = (device->buffer[7]);			input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);			/* Fall thru */		case 2:		case 3:			/* Convert buttons, only 5 bits possible */			val = (device->buffer[5]) & MASK_BUTTON;			/* We don't apply any meaning to the bitmask,			   just report */			input_event(inputdev, EV_MSC, MSC_SERIAL, val);			/*  Fall thru */		case 1:			/* All reports have X and Y coords in the same place */			val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));			input_report_abs(inputdev, ABS_X, val);			val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));			input_report_abs(inputdev, ABS_Y, val);			/* Ditto for proximity bit */			val = device->buffer[5] & MASK_INRANGE ? 1 : 0;			input_report_abs(inputdev, ABS_DISTANCE, val);			/* Report 1 is an exception to how we handle buttons */			/* Buttons are an index, not a bitmask */			if (device->buffer[0] == 1) {				/*				 * Convert buttons, 5 bit index				 * Report value of index set as one,				 * the rest as 0				 */				val = device->buffer[5] & MASK_BUTTON;				dbg("======>>>>>>REPORT 1: val 0x%X(%d)",				    val, val);				/*				 * We don't apply any meaning to the button				 * index, just report it				 */				input_event(inputdev, EV_MSC, MSC_SERIAL, val);			}			break;		case 7:			/* Menu blocks */			input_event(inputdev, EV_MSC, MSC_SCAN,				    device->buffer[1]);			break;		}	}	/* Other pid class */	if (inputdev->id.product == PID_400 ||	    inputdev->id.product == PID_401) {		/* Report 2 */		if (device->buffer[0] == 2) {			/* Menu blocks */			input_event(inputdev, EV_MSC, MSC_SCAN, device->buffer[1]);		}		/*  Report 1 */		if (device->buffer[0] == 1) {			char buttonbyte;			/*  IF X max > 64K, we still a bit from the y report */			if (device->max_X > 0x10000) {				val = (u16)(((u16)(device->buffer[2] << 8)) | (u8)device->buffer[1]);				val |= (u32)(((u8)device->buffer[3] & 0x1) << 16);				input_report_abs(inputdev, ABS_X, val);				le_buffer[0]  = (u8)((u8)(device->buffer[3]) >> 1);				le_buffer[0] |= (u8)((device->buffer[3] & 0x1) << 7);				le_buffer[1]  = (u8)(device->buffer[4] >> 1);				le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);				val = le16_to_cpu(get_unaligned((__le16 *)le_buffer));				input_report_abs(inputdev, ABS_Y, val);				/*				 * Shift the button byte right by one to				 * make it look like the standard report				 */				buttonbyte = device->buffer[5] >> 1;			} else {				val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));				input_report_abs(inputdev, ABS_X, val);				val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));				input_report_abs(inputdev, ABS_Y, val);				buttonbyte = device->buffer[5];			}			/* BUTTONS and PROXIMITY */			val = buttonbyte & MASK_INRANGE ? 1 : 0;			input_report_abs(inputdev, ABS_DISTANCE, val);			/* Convert buttons, only 4 bits possible */			val = buttonbyte & 0x0F;#ifdef USE_BUTTONS			for (i = 0; i < 5; i++)				input_report_key(inputdev, BTN_DIGI + i, val & (1 << i));#else			/* We don't apply any meaning to the bitmask, just report */			input_event(inputdev, EV_MSC, MSC_SERIAL, val);#endif			/* TRANSDUCER */			input_report_abs(inputdev, ABS_MISC, device->buffer[6]);		}	}	/* Everybody gets report ID's */	input_event(inputdev, EV_MSC, MSC_RAW,  device->buffer[0]);	/* Sync it up */	input_sync(inputdev); resubmit:	rc = usb_submit_urb(urbinfo, GFP_ATOMIC);	if (rc != 0)		err("usb_submit_urb failed rc=0x%x", rc);}/* *  The probe routine.  This is called when the kernel find the matching USB *   vendor/product.  We do the following: * *    - Allocate mem for a local structure to manage the device *    - Request a HID Report Descriptor from the device and parse it to *      find out the device parameters *    - Create an input device and assign it attributes *   - Allocate an URB so the device can talk to us when the input *      queue is open */static int gtco_probe(struct usb_interface *usbinterface,		      const struct usb_device_id *id){	struct gtco             *gtco;	struct input_dev        *input_dev;	struct hid_descriptor   *hid_desc;	char                    *report = NULL;	int                     result = 0, retry;	int			error;	struct usb_endpoint_descriptor *endpoint;	/* Allocate memory for device structure */	gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL);	input_dev = input_allocate_device();	if (!gtco || !input_dev) {		err("No more memory");		error = -ENOMEM;		goto err_free_devs;	}	/* Set pointer to the input device */	gtco->inputdevice = input_dev;	/* Save interface information */	gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));	/* Allocate some data for incoming reports */	gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE,					GFP_KERNEL, &gtco->buf_dma);	if (!gtco->buffer) {		err("No more memory for us buffers");		error = -ENOMEM;		goto err_free_devs;	}	/* Allocate URB for reports */	gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);	if (!gtco->urbinfo) {		err("Failed to allocate URB");		return -ENOMEM;		goto err_free_buf;	}	/*	 * The endpoint is always altsetting 0, we know this since we know	 * this device only has one interrupt endpoint	 */	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;	/* Some debug */	dbg("gtco # interfaces: %d", usbinterface->num_altsetting);	dbg("num endpoints:     %d", usbinterface->cur_altsetting->desc.bNumEndpoints);	dbg("interface class:   %d", usbinterface->cur_altsetting->desc.bInterfaceClass);	dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType);	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)		dbg("endpoint: we have interrupt endpoint\n");	dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen);	/*	 * Find the HID descriptor so we can find out the size of the	 * HID report descriptor	 */	if (usb_get_extra_descriptor(usbinterface->cur_altsetting,				     HID_DEVICE_TYPE, &hid_desc) != 0){		err("Can't retrieve exta USB descriptor to get hid report descriptor length");		error = -EIO;		goto err_free_urb;	}	dbg("Extra descriptor success: type:%d  len:%d",	    hid_desc->bDescriptorType,  hid_desc->wDescriptorLength);	report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);	if (!report) {		err("No more memory for report");		error = -ENOMEM;		goto err_free_urb;	}	/* Couple of tries to get reply */	for (retry = 0; retry < 3; retry++) {		result = usb_control_msg(gtco->usbdev,					 usb_rcvctrlpipe(gtco->usbdev, 0),					 USB_REQ_GET_DESCRIPTOR,					 USB_RECIP_INTERFACE | USB_DIR_IN,					 REPORT_DEVICE_TYPE << 8,					 0, /* interface */					 report,					 hid_desc->wDescriptorLength,					 5000); /* 5 secs */		if (result == hid_desc->wDescriptorLength)			break;	}	/* If we didn't get the report, fail */	dbg("usb_control_msg result: :%d", result);	if (result != hid_desc->wDescriptorLength) {		err("Failed to get HID Report Descriptor of size: %d",		    hid_desc->wDescriptorLength);		error = -EIO;		goto err_free_urb;	}	/* Now we parse the report */	parse_hid_report_descriptor(gtco, report, result);	/* Now we delete it */	kfree(report);	/* Create a device file node */	usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath));	strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath));	/* Set Input device functions */	input_dev->open = gtco_input_open;	input_dev->close = gtco_input_close;	/* Set input device information */	input_dev->name = "GTCO_CalComp";	input_dev->phys = gtco->usbpath;	input_set_drvdata(input_dev, gtco);	/* Now set up all the input device capabilities */	gtco_setup_caps(input_dev);	/* Set input device required ID information */	usb_to_input_id(gtco->usbdev, &input_dev->id);	input_dev->dev.parent = &usbinterface->dev;	/* Setup the URB, it will be posted later on open of input device */	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;	usb_fill_int_urb(gtco->urbinfo,			 gtco->usbdev,			 usb_rcvintpipe(gtco->usbdev,					endpoint->bEndpointAddress),			 gtco->buffer,			 REPORT_MAX_SIZE,			 gtco_urb_callback,			 gtco,			 endpoint->bInterval);	gtco->urbinfo->transfer_dma = gtco->buf_dma;	gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;	/* Save gtco pointer in USB interface gtco */	usb_set_intfdata(usbinterface, gtco);	/* All done, now register the input device */	error = input_register_device(input_dev);	if (error)		goto err_free_urb;	return 0; err_free_urb:	usb_free_urb(gtco->urbinfo); err_free_buf:	usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,			gtco->buffer, gtco->buf_dma); err_free_devs:	kfree(report);	input_free_device(input_dev);	kfree(gtco);	return error;}/* *  This function is a standard USB function called when the USB device *  is disconnected.  We will get rid of the URV, de-register the input *  device, and free up allocated memory */static void gtco_disconnect(struct usb_interface *interface){	/* Grab private device ptr */	struct gtco *gtco = usb_get_intfdata(interface);	/* Now reverse all the registration stuff */	if (gtco) {		input_unregister_device(gtco->inputdevice);		usb_kill_urb(gtco->urbinfo);		usb_free_urb(gtco->urbinfo);		usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE,				gtco->buffer, gtco->buf_dma);		kfree(gtco);	}	info("gtco driver disconnected");}/*   STANDARD MODULE LOAD ROUTINES  */static struct usb_driver gtco_driverinfo_table = {	.name		= "gtco",	.id_table	= gtco_usbid_table,	.probe		= gtco_probe,	.disconnect	= gtco_disconnect,};/* *  Register this module with the USB subsystem */static int __init gtco_init(void){	int error;	error = usb_register(&gtco_driverinfo_table);	if (error) {		err("usb_register() failed rc=0x%x", error);		return error;	}	printk("GTCO usb driver version: %s", GTCO_VERSION);	return 0;}/* *   Deregister this module with the USB subsystem */static void __exit gtco_exit(void){	usb_deregister(&gtco_driverinfo_table);}module_init(gtco_init);module_exit(gtco_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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