Loading drivers/usb/input/gtco.c +289 −338 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -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; Loading @@ -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 */ Loading @@ -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 */ Loading @@ -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]); /* Loading @@ -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) { Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } Loading @@ -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: Loading @@ -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; } Loading @@ -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: Loading @@ -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) { Loading @@ -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); Loading @@ -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 Loading @@ -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); } Loading @@ -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); Loading @@ -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. Loading @@ -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; Loading @@ -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; } Loading @@ -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 Loading @@ -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 */ Loading @@ -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 */ Loading @@ -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); Loading @@ -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); Loading @@ -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]); } } Loading @@ -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: Loading @@ -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, >co->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 Loading @@ -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 Loading @@ -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, Loading @@ -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; } /* Loading @@ -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(>co_driverinfo_table); if (rc) { err("usb_register() failed rc=0x%x", rc); int error; error = usb_register(>co_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; } /* Loading Loading
drivers/usb/input/gtco.c +289 −338 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -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; Loading @@ -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 */ Loading @@ -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 */ Loading @@ -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]); /* Loading @@ -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) { Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } Loading @@ -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: Loading @@ -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; } Loading @@ -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: Loading @@ -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) { Loading @@ -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); Loading @@ -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 Loading @@ -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); } Loading @@ -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); Loading @@ -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. Loading @@ -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; Loading @@ -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; } Loading @@ -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 Loading @@ -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 */ Loading @@ -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 */ Loading @@ -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); Loading @@ -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); Loading @@ -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]); } } Loading @@ -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: Loading @@ -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, >co->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 Loading @@ -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 Loading @@ -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, Loading @@ -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; } /* Loading @@ -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(>co_driverinfo_table); if (rc) { err("usb_register() failed rc=0x%x", rc); int error; error = usb_register(>co_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; } /* Loading