/*! * otg_message_ioctl() - ioctl * @param inode inode structure. * @param filp file. * @param cmd ioctl command. * @param arg ioctl argument. * @return non-zero for error. */ int otg_message_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int i; int len; int flag; struct otg_admin_command admin_command; struct otg_status_update status_update; struct otg_firmware_info firmware_info; struct otg_state otg_state; struct otg_test otg_test; //struct otg_ioctl_map *map = ioctl_map; struct otg_ioctl_name *otg_ioctl_name; static char func_buf[32]; //TRACE_MSG6(CORE, "cmd: %08x arg: %08x type: %02d nr: %02d dir: %02d size: %02d", // cmd, arg, _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_DIR(cmd), _IOC_SIZE(cmd)); RETURN_EINVAL_UNLESS (_IOC_TYPE(cmd) == OTGADMIN_MAGIC); RETURN_EINVAL_UNLESS (_IOC_NR(cmd) <= OTGADMIN_MAXNR); RETURN_EFAULT_IF((_IOC_DIR(cmd) == _IOC_READ) && !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd))); RETURN_EFAULT_IF((_IOC_DIR(cmd) == _IOC_WRITE) && !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd))); return otg_message_ioctl_internal(cmd, arg); }
int i2c_mod_init(struct otg_instance *otg) { //printk(KERN_INFO"%s:\n", __FUNCTION__); //PREPARE_WORK_ITEM(i2c_io_work_struct, &i2c_io_bh, NULL); TRACE_MSG0(otg->tcd->TAG, "INIT"); RETURN_EINVAL_UNLESS((i2c_io_task = otg_task_init2("otgi2c", i2c_io_bh, NULL, otg->tcd->TAG))); //i2c_io_task->debug = TRUE; otg_task_start(i2c_io_task); return 0; }
/*! * inteltest_cl_device_request - called to process a request to endpoint or interface * @param function * @param request * @return non-zero for failure, will cause endpoint zero stall */ static int inteltest_cl_device_request (struct usbd_function_instance *function, struct usbd_device_request *request) { struct usbd_urb *urb; u16 wLength = le16_to_cpu(request->wLength); TRACE_MSG5(GCLASS, "bmRequestType: %02x bRequest: %02x wValue: %04x wIndex: %04x wLength: %04x", request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength); /* XXX it should be this, need to verify */ RETURN_EINVAL_UNLESS(USB_REQ_RECIPIENT_DEVICE == (request->bmRequestType & USB_REQ_RECIPIENT_MASK)); switch (ctrl->bRequest) { switch (request->bmRequestType & USB_REQ_DIRECTION_MASK) { case USB_REQ_DEVICE2HOST: switch (request->bRequest) { case 0x5c: /* read test */ RETURN_EINVAL_UNLESS((urb = usbd_alloc_urb_ep0 (function, wLength, NULL))); RETURN_ZERO_UNLESS(rc || usbd_start_in_urb(urb)); break; } break; case USB_REQ_HOST2DEVICE: switch (request->bRequest) { case 0x5b: /* write test */ RETURN_EINVAL_UNLESS((urb = usbd_alloc_urb_ep0 (function, wLength, NULL))); RETURN_ZERO_UNLESS(rc || usbd_start_out_urb(urb)); break; } break; } return -EINVAL; } /* ********************************************************************************************* */ #if !defined(OTG_C99) /*! function_ops - operations table for the USB Device Core */ static struct usbd_function_operations inteltest_function_ops; /*! inteltest_class_driver - USB Device Core function driver definition */ struct usbd_class_driver inteltest_class_driver; #else /* defined(OTG_C99) */ /*! function_ops - operations table for the USB Device Core */ static struct usbd_function_operations inteltest_function_ops = { .device_request = inteltest_cl_device_request, /*!< called for each received device request */ }; /*! inteltest_class_driver - USB Device Core function driver definition */ struct usbd_class_driver inteltest_class_driver = { .driver.name = "inteltest-class", /*!< driver name */ .driver.fops = &inteltest_function_ops, /*!< operations table */ }; #endif /* defined(OTG_C99) */ /* USB Module init/exit ***************************************************** */ //#if OTG_EPILOGUE /*! * inteltest_cl_modexit() - module init * * This is called by the Linux kernel; when the module is being unloaded * if compiled as a module. This function is never called if the * driver is linked into the kernel. * @return none */ static void inteltest_cl_modexit (void) { usbd_deregister_class_function (&inteltest_class_driver); otg_trace_invalidate_tag(GCLASS); } module_exit (inteltest_cl_modexit); //#endif /*! * inteltest_cl_modinit() - module init * * This is called by the Linux kernel; either when the module is loaded * if compiled as a module, or during the system intialization if the * driver is linked into the kernel. * * This function will parse module parameters if required and then register * the inteltest driver with the USB Device software. * */ static int inteltest_cl_modinit (void) { #if !defined(OTG_C99) /*! function_ops - operations table for the USB Device Core */ ZERO(inteltest_function_ops); inteltest_function_ops.device_request=inteltest_cl_device_request; /*! called for each received device request */ /*! class_driver - USB Device Core function driver definition */ ZERO(inteltest_class_driver); inteltest_class_driver.driver.name = "inteltest-class"; /*! driver name */ inteltest_class_driver.driver.fops = &inteltest_function_ops; /*! operations table */ #endif /* defined(OTG_C99) */ GCLASS = otg_trace_obtain_tag(NULL, "inteltest-cf"); // register as usb function driver TRACE_MSG0(GCLASS, "REGISTER CLASS"); THROW_IF (usbd_register_class_function (&inteltest_class_driver, "inteltest-class", NULL), error); TRACE_MSG0(GCLASS, "REGISTER FINISHED"); CATCH(error) { inteltest_cl_modexit(); return -EINVAL; } return 0; }
/*! * otg_message_ioctl_internal() - ioctl call * @param cmd ioctl command. * @param arg ioctl arguement. * @return non-zero for error. */ int otg_message_ioctl_internal(unsigned int cmd, unsigned long arg) { int i; int len; int flag; struct otg_admin_command admin_command; struct otg_status_update status_update; struct otg_firmware_info firmware_info; struct otg_state otg_state; struct otg_test otg_test; struct otg_ioctl_name *otg_ioctl_name; static char func_buf[32]; char *sp, *dp; char *name; //printk(KERN_INFO"%s: cmd: %08x %08x\n", __FUNCTION__, cmd, _IOC_NR(cmd)); //TRACE_MSG2(CORE, "cmd: %08x %08x", cmd, _IOC_NR(cmd)); switch (_IOC_DIR(cmd)) { case _IOC_NONE: switch (_IOC_NR(cmd)) { } break; case _IOC_WRITE: switch (_IOC_NR(cmd)) { case _IOC_NR(OTGADMIN_SET_FUNCTION): TRACE_MSG0(CORE, "OTGADMIN_SET_FUNCTION"); RETURN_EINVAL_UNLESS(otg_firmware_loaded); memset(&admin_command, 0x41, sizeof(struct otg_admin_command)); RETURN_EINVAL_IF(copy_from_user(&admin_command, (void *)arg, _IOC_SIZE(cmd))); len = sizeof(mesg_otg_instance->function_name); admin_command.string[len] = '\0'; //TRACE_MSG1(CORE, "Setting function: \"%s\"", mesg_otg_instance->function_name); strncpy(mesg_otg_instance->function_name, admin_command.string, len); mesg_otg_instance->function_name[len-1] = '\0'; return 0; case _IOC_NR(OTGADMIN_SET_SERIAL): TRACE_MSG0(CORE, "OTGADMIN_SET_SERIAL"); RETURN_EINVAL_UNLESS(otg_firmware_loaded); RETURN_EINVAL_IF(copy_from_user(&admin_command, (void *)arg, _IOC_SIZE(cmd))); admin_command.string[sizeof(admin_command.string) - 1] = '\0'; //printk(KERN_INFO"%s: string: %s\n", __FUNCTION__, admin_command.string); for (sp = admin_command.string, dp = mesg_otg_instance->serial_number, i = 0; *sp && (i < (sizeof(admin_command.string) - 1)); i++, sp++) if (isxdigit(*sp)) *dp++ = toupper(*sp); *sp = '\0'; //TRACE_MSG1(CORE, "serial_number: %s", mesg_otg_instance->serial_number); printk(KERN_INFO"%s: serial: %s\n", __FUNCTION__, mesg_otg_instance->serial_number); return 0; case _IOC_NR(OTGADMIN_SET_INFO): TRACE_MSG0(CORE, "OTGADMIN_SET_INFO"); memset(&firmware_info, 0x41, sizeof(firmware_info)); RETURN_EINVAL_IF(copy_from_user(&firmware_info, (void *)arg, _IOC_SIZE(cmd))); return otg_mesg_set_firmware_info(&firmware_info); return 0; case _IOC_NR(OTGADMIN_SET_STATE): //TRACE_MSG0(CORE, "OTGADMIN_XXX_STATE"); RETURN_EINVAL_IF(copy_from_user(&otg_state, (void *)arg, _IOC_SIZE(cmd))); RETURN_EINVAL_UNLESS(otg_firmware_loading); //TRACE_MSG0(CORE, "OTGADMIN_SET_STATE"); RETURN_EINVAL_UNLESS (otg_state.state < otg_firmware_loading->number_of_states); memcpy(otg_firmware_loading->otg_states + otg_state.state, &otg_state, sizeof(otg_state)); return 0; case _IOC_NR(OTGADMIN_SET_TEST): //TRACE_MSG0(CORE, "OTGADMIN_GET/SET"); RETURN_EINVAL_IF(copy_from_user(&otg_test, (void *)arg, _IOC_SIZE(cmd))); RETURN_EINVAL_UNLESS(otg_firmware_loading); //TRACE_MSG1(CORE, "OTGADMIN_SET_TEST : %d", otg_test.test); RETURN_EINVAL_UNLESS (otg_test.test < otg_firmware_loading->number_of_tests); memcpy(otg_firmware_loading->otg_tests + otg_test.test, &otg_test, sizeof(otg_test)); return 0; } break; case _IOC_READ: switch (_IOC_NR(cmd)) { case _IOC_NR(OTGADMIN_GET_FUNCTION): TRACE_MSG0(CORE, "OTGADMIN_GET_FUNCTION"); RETURN_EINVAL_UNLESS(otg_firmware_loaded); RETURN_EINVAL_IF(copy_from_user(&admin_command, (void *)arg, _IOC_SIZE(cmd))); name = otg_usbd_ops->function_name(admin_command.n); admin_command.string[0] = '\0'; if (name) strncat(admin_command.string, name, sizeof(admin_command.string)); RETURN_EINVAL_IF(copy_to_user((void *)arg, &admin_command, _IOC_SIZE(cmd))); return 0; case _IOC_NR(OTGADMIN_GET_SERIAL): TRACE_MSG0(CORE, "OTGADMIN_GET_SERIAL"); RETURN_EINVAL_UNLESS(otg_firmware_loaded); strncpy(admin_command.string, mesg_otg_instance->serial_number, sizeof(admin_command.string)); admin_command.string[sizeof(admin_command.string) - 1] = '\0'; RETURN_EINVAL_IF(copy_to_user((void *)arg, &admin_command, _IOC_SIZE(cmd))); return 0; case _IOC_NR(OTGADMIN_STATUS): //TRACE_MSG0(CORE, "OTGADMIN_STATUS"); RETURN_EINVAL_UNLESS(otg_firmware_loaded); memset(&status_update, 0, sizeof(struct otg_status_update)); otg_mesg_get_status_update(&status_update); RETURN_EINVAL_IF(copy_to_user((void *)arg, &status_update, _IOC_SIZE(cmd))); return 0; case _IOC_NR(OTGADMIN_GET_INFO): TRACE_MSG0(CORE, "OTGADMIN_GET_INFO"); RETURN_EINVAL_UNLESS(otg_firmware_loaded); otg_mesg_get_firmware_info(&firmware_info); RETURN_EINVAL_IF(copy_to_user((void *)arg, &firmware_info, _IOC_SIZE(cmd))); //TRACE_MSG0(CORE, "OTGADMIN_GET_INFO: finished"); return 0; case _IOC_NR(OTGADMIN_GET_STATE): //TRACE_MSG0(CORE, "OTGADMIN_XXX_STATE"); RETURN_EINVAL_IF(copy_from_user(&otg_state, (void *)arg, _IOC_SIZE(cmd))); RETURN_EINVAL_UNLESS(otg_firmware_loaded); //TRACE_MSG0(CORE, "OTGADMIN_GET_STATE"); RETURN_EINVAL_UNLESS (otg_state.state < otg_firmware_loaded->number_of_states); memcpy(&otg_state, otg_firmware_loaded->otg_states + otg_state.state, sizeof(otg_state)); RETURN_EINVAL_IF(copy_to_user((void *)arg, &otg_state, _IOC_SIZE(cmd))); return 0; case _IOC_NR(OTGADMIN_GET_TEST): //TRACE_MSG0(CORE, "OTGADMIN_GET/SET"); RETURN_EINVAL_IF(copy_from_user(&otg_test, (void *)arg, _IOC_SIZE(cmd))); RETURN_EINVAL_UNLESS(otg_firmware_loaded); //TRACE_MSG1(CORE, "OTGADMIN_GET_TEST: %d", otg_test.test); RETURN_EINVAL_UNLESS (otg_test.test < otg_firmware_loaded->number_of_tests); memcpy(&otg_test, otg_firmware_loaded->otg_tests + otg_test.test, sizeof(otg_test)); RETURN_EINVAL_IF(copy_to_user((void *)arg, &otg_test, _IOC_SIZE(cmd))); return 0; } break; } TRACE_MSG0(CORE, "OTGADMIN_"); RETURN_EINVAL_UNLESS(otg_firmware_loaded); for (otg_ioctl_name = otg_ioctl_names; otg_ioctl_name && otg_ioctl_name->cmd; otg_ioctl_name++) { //TRACE_MSG4(CORE, "lookup: %04x %04x %08x %08x", // _IOC_NR(cmd), _IOC_NR(otg_ioctl_name->cmd), cmd, otg_ioctl_name->cmd); BREAK_IF(_IOC_NR(otg_ioctl_name->cmd) == _IOC_NR(cmd)); } //TRACE_MSG3(CORE, "checking %d %08x %08x", _IOC_NR(cmd), otg_ioctl_name->cmd, cmd); RETURN_EINVAL_UNLESS(otg_ioctl_name->cmd); __get_user(flag, (int *)arg); //TRACE_MSG3(CORE, "%s %08x flag: %d", otg_ioctl_name->name, otg_ioctl_name->set, flag); otg_event (mesg_otg_instance, flag ? otg_ioctl_name->set : _NOT(otg_ioctl_name->set), CORE, otg_ioctl_name->name); return 0; }