Commit 1b726a02 authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Input: gtco - handle errors from input_register_device()



Also fix URB leak in gtco_probe error path, formatting fixes.

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 55d29c98
Loading
Loading
Loading
Loading
+289 −338
Original line number Diff line number Diff line
@@ -187,7 +187,6 @@ struct hid_descriptor


/*
 *
 *   This is an abbreviated parser for the HID Report Descriptor.  We
 *   know what devices we are talking to, so this is by no means meant
 *   to be generic.  We can make some safe assumptions:
@@ -215,7 +214,6 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
	__u16  data16 = 0;
	__u32  data32 = 0;


	/* For parsing logic */
	int   inputnum = 0;
	__u32 usage = 0;
@@ -231,7 +229,6 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
	char  indentstr[10] = "";



	dbg("======>>>>>>PARSE<<<<<<======");

	/* Walk  this report and pull out the info we need */
@@ -248,11 +245,12 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
			data = report[i];
			break;
		case 2:
			data16 = le16_to_cpu(get_unaligned((__le16*)(&(report[i]))));
			data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i]));
			break;
		case 3:
			size = 4;
			data32 = le32_to_cpu(get_unaligned((__le32*)(&(report[i]))));
			data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i]));
			break;
		}

		/* Skip size of data */
@@ -275,18 +273,16 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
				 */

				maintype = 'I';
				if (data==2){
				if (data == 2)
					strcpy(globtype, "Variable");
				}
				if (data==3){
				else if (data == 3)
					strcpy(globtype, "Var|Const");
				}

				dbg("::::: Saving Report: %d input #%d Max: 0x%X(%d) Min:0x%X(%d) of %d bits",
				    globalval[TAG_GLOB_REPORT_ID], inputnum,
				    globalval[TAG_GLOB_LOG_MAX], globalval[TAG_GLOB_LOG_MAX],
				    globalval[TAG_GLOB_LOG_MIN], globalval[TAG_GLOB_LOG_MIN],
				    (globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]));
				    globalval[TAG_GLOB_REPORT_SZ] * globalval[TAG_GLOB_REPORT_CNT]);


				/*
@@ -302,8 +298,8 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
						device->max_X = globalval[TAG_GLOB_LOG_MAX];
						device->min_X = globalval[TAG_GLOB_LOG_MIN];
					}

					break;

				case 1:  /* Y coord */
					dbg("GER: Y Usage: 0x%x", usage);
					if (device->max_Y == 0) {
@@ -311,6 +307,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
						device->min_Y = globalval[TAG_GLOB_LOG_MIN];
					}
					break;

				default:
					/* Tilt X */
					if (usage == DIGITIZER_USAGE_TILT_X) {
@@ -328,7 +325,6 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
						}
					}


					/* Pressure */
					if (usage == DIGITIZER_USAGE_TIP_PRESSURE) {
						if (device->maxpressure == 0) {
@@ -341,51 +337,48 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
				}

				inputnum++;


				break;

			case TAG_MAIN_OUTPUT:
				maintype = 'O';
				break;

			case TAG_MAIN_FEATURE:
				maintype = 'F';
				break;

			case TAG_MAIN_COL_START:
				maintype = 'S';

				if (data == 0) {
					dbg("======>>>>>> Physical");
					strcpy(globtype, "Physical");
				}else{
				} else
					dbg("======>>>>>>");
				}

				/* Indent the debug output */
				indent++;
				for (x=0;x<indent;x++){
				for (x = 0; x < indent; x++)
					indentstr[x] = '-';
				}
				indentstr[x] = 0;

				/* Save global tags */
				for (x=0;x<TAG_GLOB_MAX;x++){
				for (x = 0; x < TAG_GLOB_MAX; x++)
					oldval[x] = globalval[x];
				}

				break;

			case TAG_MAIN_COL_END:
				dbg("<<<<<<======");
				maintype = 'E';
				indent--;
				for (x=0;x<indent;x++){
				for (x = 0; x < indent; x++)
					indentstr[x] = '-';
				}
				indentstr[x] = 0;

				/* Copy global tags back */
				for (x=0;x<TAG_GLOB_MAX;x++){
				for (x = 0; x < TAG_GLOB_MAX; x++)
					globalval[x] = oldval[x];
				}

				break;
			}
@@ -395,16 +388,19 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
				    indentstr, tag, maintype, size, globtype, data);
				break;

			case 2:
				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
				    indentstr, tag, maintype, size, globtype, data16);
				break;

			case 4:
				dbg("%sMAINTAG:(%d) %c SIZE: %d Data: %s 0x%x",
				    indentstr, tag, maintype, size, globtype, data32);
				break;
			}
			break;

		case TYPE_GLOBAL:
			switch (tag) {
			case TAG_GLOB_USAGE:
@@ -412,63 +408,78 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
				 * First time we hit the global usage tag,
				 * it should tell us the type of device
				 */
				if (device->usage == 0){
				if (device->usage == 0)
					device->usage = data;
				}

				strcpy(globtype, "USAGE");
				break;

			case TAG_GLOB_LOG_MIN:
				strcpy(globtype, "LOG_MIN");
				break;

			case TAG_GLOB_LOG_MAX:
				strcpy(globtype, "LOG_MAX");
				break;

			case TAG_GLOB_PHYS_MIN:
				strcpy(globtype, "PHYS_MIN");
				break;

			case TAG_GLOB_PHYS_MAX:
				strcpy(globtype, "PHYS_MAX");
				break;

			case TAG_GLOB_UNIT_EXP:
				strcpy(globtype, "EXP");
				break;

			case TAG_GLOB_UNIT:
				strcpy(globtype, "UNIT");
				break;

			case TAG_GLOB_REPORT_SZ:
				strcpy(globtype, "REPORT_SZ");
				break;

			case TAG_GLOB_REPORT_ID:
				strcpy(globtype, "REPORT_ID");
				/* New report, restart numbering */
				inputnum = 0;
				break;

			case TAG_GLOB_REPORT_CNT:
				strcpy(globtype, "REPORT_CNT");
				break;

			case TAG_GLOB_PUSH:
				strcpy(globtype, "PUSH");
				break;

			case TAG_GLOB_POP:
				strcpy(globtype, "POP");
				break;
			}


			/* Check to make sure we have a good tag number
			   so we don't overflow array */
			if (tag < TAG_GLOB_MAX) {
				switch (size) {
				case 1:
					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data);
					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
					    indentstr, globtype, tag, size, data);
					globalval[tag] = data;
					break;

				case 2:
					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data16);
					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
					    indentstr, globtype, tag, size, data16);
					globalval[tag] = data16;
					break;

				case 4:
					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",indentstr,globtype,tag,size,data32);
					dbg("%sGLOBALTAG:%s(%d) SIZE: %d Data: 0x%x",
					    indentstr, globtype, tag, size, data32);
					globalval[tag] = data32;
					break;
				}
@@ -476,8 +487,6 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
				dbg("%sGLOBALTAG: ILLEGAL TAG:%d SIZE: %d ",
				    indentstr, tag, size);
			}


			break;

		case TYPE_LOCAL:
@@ -487,14 +496,18 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
				/* Always 1 byte */
				usage = data;
				break;

			case TAG_GLOB_LOG_MIN:
				strcpy(globtype, "MIN");
				break;

			case TAG_GLOB_LOG_MAX:
				strcpy(globtype, "MAX");
				break;

			default:
				strcpy(globtype, "UNKNOWN");
				break;
			}

			switch (size) {
@@ -502,10 +515,12 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
				    indentstr, tag, globtype, size, data);
				break;

			case 2:
				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
				    indentstr, tag, globtype, size, data16);
				break;

			case 4:
				dbg("%sLOCALTAG:(%d) %s SIZE: %d Data: 0x%x",
				    indentstr, tag, globtype, size, data32);
@@ -514,16 +529,11 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,

			break;
		}

	}

}



/*   INPUT DRIVER Routines                               */


/*
 * Called when opening the input device.  This will submit the URB to
 * the usb system so we start getting reports
@@ -534,21 +544,20 @@ static int gtco_input_open(struct input_dev *inputdev)
	device = inputdev->private;

	device->urbinfo->dev = device->usbdev;
	if (usb_submit_urb(device->urbinfo, GFP_KERNEL)) {
	if (usb_submit_urb(device->urbinfo, GFP_KERNEL))
		return -EIO;
	}

	return 0;
}

/**
    Called when closing the input device.  This will unlink the URB
/*
 * Called when closing the input device.  This will unlink the URB
 */
static void gtco_input_close(struct input_dev *inputdev)
{
	struct gtco *device = inputdev->private;

	usb_kill_urb(device->urbinfo);

}


@@ -564,15 +573,12 @@ static void gtco_setup_caps(struct input_dev *inputdev)
{
	struct gtco *device = inputdev->private;


	/* Which events */
	inputdev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);


	/* Misc event menu block */
	inputdev->mscbit[0] = BIT(MSC_SCAN)|BIT(MSC_SERIAL)|BIT(MSC_RAW) ;


	/* Absolute values based on HID report info */
	input_set_abs_params(inputdev, ABS_X, device->min_X, device->max_X,
			     0, 0);
@@ -590,17 +596,12 @@ static void gtco_setup_caps(struct input_dev *inputdev)
	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.
@@ -610,8 +611,6 @@ static void gtco_setup_caps(struct input_dev *inputdev)
 */
static void gtco_urb_callback(struct urb *urbinfo)
{


	struct gtco *device = urbinfo->context;
	struct input_dev  *inputdev;
	int               rc;
@@ -621,19 +620,20 @@ static void gtco_urb_callback(struct urb *urbinfo)

	inputdev = device->inputdevice;


	/* Was callback OK? */
	if ((urbinfo->status == -ECONNRESET ) ||
	    (urbinfo->status == -ENOENT ) ||
	    (urbinfo->status == -ESHUTDOWN )){
	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 */
		/*
		 * Some unknown error.  Hopefully temporary. Just go and
		 * requeue an URB
		 */
		goto resubmit;
	}

@@ -642,10 +642,9 @@ static void gtco_urb_callback(struct urb *urbinfo)
	 */

	/* PID dependent when we interpret the report */
	if ((inputdev->id.product == PID_1000 )||
	    (inputdev->id.product == PID_1001 )||
	    (inputdev->id.product == PID_1002 ))
	{
	if (inputdev->id.product == PID_1000 ||
	    inputdev->id.product == PID_1001 ||
	    inputdev->id.product == PID_1002) {

		/*
		 * Switch on the report ID
@@ -664,7 +663,6 @@ static void gtco_urb_callback(struct urb *urbinfo)
			/* Mask out the Y tilt value used for pressure */
			device->buffer[7] = (u8)((device->buffer[7]) & 0x7F);


			/* Fall thru */
		case 4:
			/* Tilt */
@@ -684,7 +682,6 @@ static void gtco_urb_callback(struct urb *urbinfo)
			input_report_abs(inputdev, ABS_TILT_Y, (s32)valsigned);

			/* Fall thru */

		case 2:
		case 3:
			/* Convert buttons, only 5 bits possible */
@@ -696,31 +693,26 @@ static void gtco_urb_callback(struct urb *urbinfo)

			/*  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])));
			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])));
			val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
			input_report_abs(inputdev, ABS_Y, val);


			/* Ditto for proximity bit */
			if (device->buffer[5]& MASK_INRANGE){
				val = 1;
			}else{
				val=0;
			}
			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 */
				/*
				 * 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);
@@ -730,44 +722,35 @@ static void gtco_urb_callback(struct urb *urbinfo)
				 * 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 ))
	{
	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]);
			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 = (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);
@@ -778,50 +761,41 @@ static void gtco_urb_callback(struct urb *urbinfo)
				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)));

				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;
				buttonbyte = device->buffer[5] >> 1;
			} else {

				val = le16_to_cpu(get_unaligned((__le16 *) (&(device->buffer[1]))));
				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]))));
				val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
				input_report_abs(inputdev, ABS_Y, val);

				buttonbyte = device->buffer[5];

			}


			/* BUTTONS and PROXIMITY */
			if (buttonbyte& MASK_INRANGE){
				val = 1;
			}else{
				val=0;
			}
			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++){
			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]);

		}
	}

@@ -833,12 +807,10 @@ static void gtco_urb_callback(struct urb *urbinfo)

 resubmit:
	rc = usb_submit_urb(urbinfo, GFP_ATOMIC);
	if (rc != 0) {
	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:
@@ -854,58 +826,46 @@ static int gtco_probe(struct usb_interface *usbinterface,
		      const struct usb_device_id *id)
{

	struct gtco             *device = NULL;
	char                    path[PATHLENGTH];
	struct input_dev        *inputdev;
	struct gtco             *gtco;
	struct input_dev        *input_dev;
	struct hid_descriptor   *hid_desc;
	char                    *report;
	char                    *report = NULL;
	int                     result = 0, retry;
	int			error;
	struct usb_endpoint_descriptor *endpoint;

	/* Allocate memory for device structure */
	device = kzalloc(sizeof(struct gtco), GFP_KERNEL);
	if (device == NULL) {
		err("No more memory");
		return -ENOMEM;
	}


	device->inputdevice = input_allocate_device();
	if (!device->inputdevice){
		kfree(device);
	gtco = kzalloc(sizeof(struct gtco), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!gtco || !input_dev) {
		err("No more memory");
		return -ENOMEM;
		error = -ENOMEM;
		goto err_free_devs;
	}

	/* Get pointer to the input device */
	inputdev = device->inputdevice;
	/* Set pointer to the input device */
	gtco->inputdevice = input_dev;

	/* Save interface information */
	device->usbdev     = usb_get_dev(interface_to_usbdev(usbinterface));

	gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));

	/* Allocate some data for incoming reports */
	device->buffer = usb_buffer_alloc(device->usbdev, REPORT_MAX_SIZE,
					   GFP_KERNEL, &(device->buf_dma));
	if (!device->buffer){
		input_free_device(device->inputdevice);
		kfree(device);
		err("No more memory");
		return -ENOMEM;
	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 */
	device->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
	if (!device->urbinfo) {
		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
				device->buffer, device->buf_dma);
		input_free_device(device->inputdevice);
		kfree(device);
		err("No more memory");
	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
@@ -922,8 +882,6 @@ static int gtco_probe(struct usb_interface *usbinterface,

	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
@@ -931,33 +889,27 @@ static int gtco_probe(struct usb_interface *usbinterface,
	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");
		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
				device->buffer, device->buf_dma);
		input_free_device(device->inputdevice);
		kfree(device);
		return -EIO;
		error = -EIO;
		goto err_free_urb;
	}

	dbg("Extra descriptor success: type:%d  len:%d",
	    hid_desc->bDescriptorType,  hid_desc->wDescriptorLength);

	if (!(report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL))) {
		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
				device->buffer, device->buf_dma);

		input_free_device(device->inputdevice);
		kfree(device);
		err("No more memory");
		return -ENOMEM;
	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(device->usbdev,
					 usb_rcvctrlpipe(device->usbdev, 0),
		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),
					 REPORT_DEVICE_TYPE << 8,
					 0, /* interface */
					 report,
					 hid_desc->wDescriptorLength,
@@ -970,71 +922,74 @@ static int gtco_probe(struct usb_interface *usbinterface,
	/* If we didn't get the report, fail */
	dbg("usb_control_msg result: :%d", result);
	if (result != hid_desc->wDescriptorLength) {
		kfree(report);
		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
				device->buffer, device->buf_dma);
		input_free_device(device->inputdevice);
		kfree(device);
		err("Failed to get HID Report Descriptor of size: %d",
		    hid_desc->wDescriptorLength);
		return -EIO;
		error = -EIO;
		goto err_free_urb;
	}


	/* Now we parse the report */
	parse_hid_report_descriptor(device,report,result);
	parse_hid_report_descriptor(gtco, report, result);

	/* Now we delete it */
	kfree(report);

	/* Create a device file node */
	usb_make_path(device->usbdev, path, PATHLENGTH);
	sprintf(device->usbpath, "%s/input0", path);

	usb_make_path(gtco->usbdev, gtco->usbpath, sizeof(gtco->usbpath));
	strlcat(gtco->usbpath, "/input0", sizeof(gtco->usbpath));

	/* Set Input device functions */
	inputdev->open     = gtco_input_open;
	inputdev->close    = gtco_input_close;
	input_dev->open = gtco_input_open;
	input_dev->close = gtco_input_close;

	/* Set input device information */
	inputdev->name     = "GTCO_CalComp";
	inputdev->phys     = device->usbpath;
	inputdev->private  = device;

	input_dev->name = "GTCO_CalComp";
	input_dev->phys = gtco->usbpath;
	input_dev->private = gtco;

	/* Now set up all the input device capabilities */
	gtco_setup_caps(inputdev);
	gtco_setup_caps(input_dev);

	/* Set input device required ID information */
	usb_to_input_id(device->usbdev, &device->inputdevice->id);
	inputdev->cdev.dev = &usbinterface->dev;
	usb_to_input_id(gtco->usbdev, &input_dev->id);
	input_dev->cdev.dev = &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(device->urbinfo,
			 device->usbdev,
			 usb_rcvintpipe(device->usbdev,
	usb_fill_int_urb(gtco->urbinfo,
			 gtco->usbdev,
			 usb_rcvintpipe(gtco->usbdev,
					endpoint->bEndpointAddress),
			 device->buffer,
			 gtco->buffer,
			 REPORT_MAX_SIZE,
			 gtco_urb_callback,
			 device,
			 gtco,
			 endpoint->bInterval);

	device->urbinfo->transfer_dma = device->buf_dma;
	device->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	gtco->urbinfo->transfer_dma = gtco->buf_dma;
	gtco->urbinfo->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	/* Save device pointer in USB interface device */
	usb_set_intfdata(usbinterface, device);
	/* Save gtco pointer in USB interface gtco */
	usb_set_intfdata(usbinterface, gtco);

	/* All done, now register the input device */
	input_register_device(inputdev);
	error = input_register_device(input_dev);
	if (error)
		goto err_free_urb;

	info( "gtco driver created usb:  %s\n",  path);
	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;
}

/*
@@ -1044,50 +999,46 @@ static int gtco_probe(struct usb_interface *usbinterface,
 */
static void gtco_disconnect(struct usb_interface *interface)
{

	/* Grab private device ptr */
	struct gtco    *device = usb_get_intfdata (interface);
	struct input_dev *inputdev;

	inputdev = device->inputdevice;
	struct gtco *gtco = usb_get_intfdata(interface);

	/* Now reverse all the registration stuff */
	if (device) {
		input_unregister_device(inputdev);
		usb_kill_urb(device->urbinfo);
		usb_free_urb(device->urbinfo);
		usb_buffer_free(device->usbdev, REPORT_MAX_SIZE,
				device->buffer, device->buf_dma);
		kfree(device);
	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 = {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
	.owner      = THIS_MODULE,
#endif
	.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 rc;
	rc = usb_register(&gtco_driverinfo_table);
	if (rc) {
		err("usb_register() failed rc=0x%x", rc);
	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 rc;
	return 0;
}

/*