static int ioctl_usbpd(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct USBPDCommand usbpd_cmd; struct usbpd_usb_data *usbpd = file->private_data; void *data; unsigned char *buffer; int result = 0, requesttype; /* Sanity check to make sure usbpd is connected, powered, etc */ if ( usbpd == NULL ) return -EINVAL; down(&usbpd->lock); if ( usbpd->present == 0 || usbpd->usbpd_dev == NULL ) { up(&usbpd->lock); return -EINVAL; } switch (cmd) { case USBPD_RECV_COMMAND: dbg("USBPD_RECV_COMMAND"); data = (void *) arg; if (data == NULL) break; if (copy_from_user(&usbpd_cmd, data, sizeof(struct USBPDCommand))) { up(&usbpd->lock); return -EFAULT; } if (usbpd_cmd.length > PAGE_SIZE) { up(&usbpd->lock); return -EINVAL; } buffer = (unsigned char *) __get_free_page(GFP_KERNEL); if (buffer == NULL) { up(&usbpd->lock); return -ENOMEM; } if (copy_from_user(buffer, usbpd_cmd.buffer, usbpd_cmd.length)) { up(&usbpd->lock); return -EFAULT; } requesttype = usbpd_cmd.requesttype | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; dbg ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x", requesttype, usbpd_cmd.request, usbpd_cmd.value, usbpd_cmd.index, usbpd_cmd.length); /* Send usbpd control message */ result = usb_control_msg(usbpd->usbpd_dev, usb_rcvctrlpipe(usbpd-> usbpd_dev, 0), usbpd_cmd.request, requesttype, usbpd_cmd.value, usbpd_cmd.index, buffer, usbpd_cmd.length, usbpd_cmd.timeout); if (result < 0) { err("Error executing ioctrl. code = %d", le32_to_cpu(result)); } else { dbg("Executed ioctl. Result = %d (data=%04x)", le32_to_cpu(result), le32_to_cpu(*((long *) buffer))); if (copy_to_user(usbpd_cmd.buffer, buffer, usbpd_cmd.length)) { up(&usbpd->lock); return -EFAULT; } } /* usbpd_cmd.buffer contains a raw stream of single byte data which has been returned from usbpd. Data is interpreted at application level. For data that will be cast to data types longer than 1 byte, data will be little_endian and will potentially need to be swapped at the app level */ free_page((unsigned long) buffer); break; case USBPD_SEND_COMMAND: dbg("USBPD_SEND_COMMAND"); data = (void *) arg; if (data == NULL) break; if (copy_from_user(&usbpd_cmd, data, sizeof(struct USBPDCommand))) { up(&usbpd->lock); return -EFAULT; } if (usbpd_cmd.length > PAGE_SIZE) { up(&usbpd->lock); return -EINVAL; } buffer = (unsigned char *) __get_free_page(GFP_KERNEL); if (buffer == NULL) { up(&usbpd->lock); return -ENOMEM; } if (copy_from_user(buffer, usbpd_cmd.buffer, usbpd_cmd.length)) { up(&usbpd->lock); return -EFAULT; } requesttype = usbpd_cmd.requesttype | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x", requesttype, usbpd_cmd.request, usbpd_cmd.value, usbpd_cmd.index, usbpd_cmd.length); /* Send usbpd control message */ result = usb_control_msg(usbpd->usbpd_dev, usb_sndctrlpipe(usbpd-> usbpd_dev, 0), usbpd_cmd.request, requesttype, usbpd_cmd.value, usbpd_cmd.index, buffer, usbpd_cmd.length, usbpd_cmd.timeout); if (result < 0) { err("Error executing ioctrl. code = %d", le32_to_cpu(result)); } else { dbg("Executed ioctl. Result = %d", le32_to_cpu(result)); } free_page((unsigned long) buffer); break; case USBPD_DEVICE_INFO: data = (void *) arg; if (data == NULL) break; usb_get_configuration(usbpd->usbpd_dev); dbg("deviceID = %x ProductID = %x", usbpd->usbpd_dev->descriptor.idVendor, usbpd->usbpd_dev->descriptor.idProduct); copy_to_user(data, &usbpd->usbpd_dev->descriptor, sizeof(struct usb_device_descriptor)); copy_to_user(data+sizeof(struct usb_device_descriptor), &usbpd->usbpd_dev->devnum, sizeof(int)); copy_to_user(data+sizeof(struct usb_device_descriptor)+sizeof(int), &usbpd->pdtype, sizeof(int)); break; default: up(&usbpd->lock); return -ENOIOCTLCMD; break; } up(&usbpd->lock); return (result < 0) ? result : 0; }
/* * WARNING - If a driver calls usb_reset_device, you should simulate a * disconnect() and probe() for other interfaces you doesn't claim. This * is left up to the driver writer right now. This insures other drivers * have a chance to re-setup their interface. * * Take a look at proc_resetdevice in devio.c for some sample code to * do this. */ int usb_reset_device(struct usb_device *dev) { struct usb_device *parent = dev->parent; struct usb_device_descriptor descriptor; int i, ret, port = -1; DBG_HOST_HUB("### >>> Enter hub.c file --> usb_reset_device function \n"); if (!parent) { err("attempting to reset root hub!"); return -EINVAL; } for (i = 0; i < parent->maxchild; i++) if (parent->children[i] == dev) { port = i; break; } if (port < 0) return -ENOENT; down(&usb_address0_sem); /* Send a reset to the device */ if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) { usb_hub_port_disable(parent, port); up(&usb_address0_sem); return(-ENODEV); } /* Reprogram the Address */ ret = usb_set_address(dev); if (ret < 0) { err("USB device not accepting new address (error=%d)", ret); usb_hub_port_disable(parent, port); up(&usb_address0_sem); return ret; } /* Let the SET_ADDRESS settle */ wait_ms(10); up(&usb_address0_sem); /* * Now we fetch the configuration descriptors for the device and * see if anything has changed. If it has, we dump the current * parsed descriptors and reparse from scratch. Then we leave * the device alone for the caller to finish setting up. * * If nothing changed, we reprogram the configuration and then * the alternate settings. */ ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor, sizeof(descriptor)); if (ret < 0) return ret; le16_to_cpus(&descriptor.bcdUSB); le16_to_cpus(&descriptor.idVendor); le16_to_cpus(&descriptor.idProduct); le16_to_cpus(&descriptor.bcdDevice); if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) { usb_destroy_configuration(dev); ret = usb_get_device_descriptor(dev); if (ret < sizeof(dev->descriptor)) { if (ret < 0) err("unable to get device descriptor (error=%d)", ret); else err("USB device descriptor short read (expected %Zi, got %i)", sizeof(dev->descriptor), ret); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return -EIO; } ret = usb_get_configuration(dev); if (ret < 0) { err("unable to get configuration (error=%d)", ret); usb_destroy_configuration(dev); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dev->actconfig = dev->config; usb_set_maxpacket(dev); return 1; } ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue); if (ret < 0) { err("failed to set active configuration (error=%d)", ret); return ret; } for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { struct usb_interface *intf = &dev->actconfig->interface[i]; struct usb_interface_descriptor *as = &intf->altsetting[intf->act_altsetting]; ret = usb_set_interface(dev, as->bInterfaceNumber, as->bAlternateSetting); if (ret < 0) { err("failed to set active alternate setting for interface %d (error=%d)", i, ret); return ret; } } return 0; }
//! This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! If the received request is not supported or a non-standard USB request, the function //! will call the custom decoding function in usb_specific_request module. //! //! @note List of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bRequest; Usb_reset_endpoint_fifo_access(EP_CONTROL); bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8); bRequest = Usb_read_endpoint_data(EP_CONTROL, 8); switch (bRequest) { case GET_DESCRIPTOR: if (bmRequestType == 0x80) usb_get_descriptor(); else goto unsupported_request; break; case GET_CONFIGURATION: if (bmRequestType == 0x80) usb_get_configuration(); else goto unsupported_request; break; case SET_ADDRESS: if (bmRequestType == 0x00) usb_set_address(); else goto unsupported_request; break; case SET_CONFIGURATION: if (bmRequestType == 0x00) usb_set_configuration(); else goto unsupported_request; break; case CLEAR_FEATURE: if (bmRequestType <= 0x02) usb_clear_feature(); else goto unsupported_request; break; case SET_FEATURE: if (bmRequestType <= 0x02) usb_set_feature(); else goto unsupported_request; break; case GET_STATUS: if (0x7F < bmRequestType && bmRequestType <= 0x82) usb_get_status(); else goto unsupported_request; break; case GET_INTERFACE: if (bmRequestType == 0x81) { if(!usb_get_interface()) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); } } else goto unsupported_request; break; case SET_INTERFACE: if (bmRequestType == 0x01) usb_set_interface(); else goto unsupported_request; break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< unsupported request => call to user read request unsupported_request: if (!usb_user_read_request(bmRequestType, bRequest)) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); } break; } }
//! usb_process_request. //! //! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! @param none //! //! @return none //! @note list of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bmRequest; bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_INTERFACE: if (bmRequestType == 0x01) {usb_set_interface();} break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request if(usb_user_read_request(bmRequestType, bmRequest) == FALSE) { Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } break; } }
//! usb_process_request. //! //! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! @note list of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bmRequest; bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } else goto user_read; break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } else goto user_read; break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } else goto user_read; break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } else goto user_read; break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } else goto user_read; break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } else goto user_read; break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } else goto user_read; break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } else goto user_read; break; case SET_INTERFACE: if (bmRequestType == 0x01) {usb_set_interface();} break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request user_read: usb_user_read_request(bmRequestType, bmRequest); break; } Usb_select_endpoint(EP_CONTROL); // If the receive setup flag hasn't been cleared // by this point then we can assume that we didn't // support this request and should stall. if(Is_usb_receive_setup()) Usb_enable_stall_handshake(); // Clear some flags. Usb_ack_receive_setup(); Usb_ack_receive_out(); Usb_ack_in_ready(); }
/* * Read the SETUP request sent to the default control endpoint * and call the appropriate function. When exiting this * function, the device is ready to manage the next request. * * Supported requests: * GET_DESCRIPTOR * GET_CONFIGURATION * SET_ADDRESS * SET_CONFIGURATION * CLEAR_FEATURE * SET_FEATURE * GET_STATUS */ void OSUsbDeviceImpl::standardProcessRequest(void) { unsigned char bmRequest; bmRequestType = OSUsbDeviceImpl::readByte(); bmRequest = OSUsbDeviceImpl::readByte(); #if defined(DEBUG) && defined(OS_DEBUG_OSUSBDEVICE_REQUEST) OSDeviceDebug::putString("type/req="); OSDeviceDebug::putHex(bmRequestType); OSDeviceDebug::putString("/"); OSDeviceDebug::putHex(bmRequest); OSDeviceDebug::putString(" "); //OSDeviceDebug::putNewLine(); #endif switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { OSUsbDeviceImpl::usb_get_descriptor(); return; } break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); return; } break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); return; } break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); return; } break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); return; } break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); return; } break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); return; } break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); return; } break; case SET_INTERFACE: if (bmRequestType == 0x01) { usb_set_interface(); return; } break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: break; } // for un-supported requests call the specific read request if (OSUsbDeviceImpl::specificProcessReadRequest(bmRequestType, bmRequest)) return; // if nothing worked, reply with stall OSUsbDeviceImpl::Usb_enable_stall_handshake(); OSUsbDeviceImpl::Usb_ack_receive_setup(); }
//! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! void usb_process_request(void) { U8 bmRequestType; U8 bmRequest; Usb_ack_control_out(); bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case SETUP_GET_DESCRIPTOR: if (USB_SETUP_GET_STAND_DEVICE == bmRequestType) { if( usb_get_descriptor() ) return; } break; case SETUP_GET_CONFIGURATION: if (USB_SETUP_GET_STAND_DEVICE == bmRequestType) { usb_get_configuration(); return; } break; case SETUP_SET_ADDRESS: if (USB_SETUP_SET_STAND_DEVICE == bmRequestType) { usb_set_address(); return; } break; case SETUP_SET_CONFIGURATION: if (USB_SETUP_SET_STAND_DEVICE == bmRequestType) { if( usb_set_configuration() ) return; } break; case SETUP_CLEAR_FEATURE: if (usb_clear_feature(bmRequestType)) return; break; case SETUP_SET_FEATURE: if (usb_set_feature(bmRequestType)) return; break; case SETUP_GET_STATUS: if (usb_get_status(bmRequestType)) return; break; case SETUP_GET_INTERFACE: if (USB_SETUP_GET_STAND_INTERFACE == bmRequestType) { if( usb_get_interface() ) return; } break; case SETUP_SET_INTERFACE: if (bmRequestType == USB_SETUP_SET_STAND_INTERFACE) { if( usb_set_interface() ) return; } break; default: break; } // un-supported like standard request => call to user read request if( !usb_user_read_request(bmRequestType, bmRequest) ) { // Request unknow in the specific request list from interface // keep that order (set StallRq/clear RxSetup) or a // OUT request following the SETUP may be acknowledged Usb_enable_stall_handshake(); Usb_ack_receive_setup(); endpoint_status[(EP_CONTROL & MSK_EP_DIR)] = 0x01; } }