setup_out_ready : 1,
setup_out_error : 1,
setup_abort : 1;
+ unsigned setup_wLength;
/* the rest is basically write-once */
struct usb_config_descriptor *config, *hs_config;
{
struct dev_data *dev;
- dev = kmalloc (sizeof *dev, GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return NULL;
- memset (dev, 0, sizeof *dev);
dev->state = STATE_DEV_DISABLED;
atomic_set (&dev->count, 1);
spin_lock_init (&dev->lock);
*
* After opening, configure non-control endpoints. Then use normal
* stream read() and write() requests; and maybe ioctl() to get more
- * precise FIFO status when recovering from cancelation.
+ * precise FIFO status when recovering from cancellation.
*/
static void epio_complete (struct usb_ep *ep, struct usb_request *req)
goto free1;
value = ep_io (data, kbuf, len);
- VDEBUG (data->dev, "%s read %d OUT, status %d\n",
- data->name, len, value);
+ VDEBUG (data->dev, "%s read %zu OUT, status %d\n",
+ data->name, len, (int) value);
if (value >= 0 && copy_to_user (buf, kbuf, value))
value = -EFAULT;
}
value = ep_io (data, kbuf, len);
- VDEBUG (data->dev, "%s write %d IN, status %d\n",
- data->name, len, value);
+ VDEBUG (data->dev, "%s write %zu IN, status %d\n",
+ data->name, len, (int) value);
free1:
up (&data->lock);
kfree (kbuf);
data->state = STATE_EP_DISABLED;
data->desc.bDescriptorType = 0;
data->hs_desc.bDescriptorType = 0;
+ usb_ep_disable(data->ep);
}
put_ep (data);
return 0;
if (value == 0)
data->state = STATE_EP_ENABLED;
break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_SPEED_HIGH:
/* fails if caller didn't provide that descriptor... */
value = usb_ep_enable (ep, &data->hs_desc);
}
req->complete = ep0_complete;
req->length = len;
+ req->zero = 0;
return 0;
}
/* assume that was SET_CONFIGURATION */
if (dev->current_config) {
unsigned power;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (dev->gadget->speed == USB_SPEED_HIGH)
power = dev->hs_config->bMaxPower;
else
spin_unlock_irq (&dev->lock);
if (copy_from_user (dev->req->buf, buf, len))
retval = -EFAULT;
- else
+ else {
+ if (len < dev->setup_wLength)
+ dev->req->zero = 1;
retval = usb_ep_queue (
dev->gadget->ep0, dev->req,
GFP_KERNEL);
+ }
if (retval < 0) {
spin_lock_irq (&dev->lock);
clean_req (dev->gadget->ep0, dev->req);
* Unrecognized ep0 requests may be handled in user space.
*/
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
static void make_qualifier (struct dev_data *dev)
{
struct usb_qualifier_descriptor qual;
config_buf (struct dev_data *dev, u8 type, unsigned index)
{
int len;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
int hs;
#endif
if (index > 0)
return -EINVAL;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
hs = (dev->gadget->speed == USB_SPEED_HIGH);
if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs;
struct usb_request *req = dev->req;
int value = -EOPNOTSUPP;
struct usb_gadgetfs_event *event;
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
spin_lock (&dev->lock);
dev->setup_abort = 0;
dev->state = STATE_CONNECTED;
dev->dev->bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) {
ERROR (dev, "no high speed config??\n");
return -EINVAL;
}
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
INFO (dev, "connected\n");
event = next_event (dev, GADGETFS_CONNECT);
/* ... down_trylock (&data->lock) ... */
if (data->state != STATE_EP_DEFER_ENABLE)
continue;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH)
value = usb_ep_enable (ep, &data->hs_desc);
else
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
value = usb_ep_enable (ep, &data->desc);
if (value) {
ERROR (dev, "deferred %s enable --> %d\n",
case USB_REQ_GET_DESCRIPTOR:
if (ctrl->bRequestType != USB_DIR_IN)
goto unrecognized;
- switch (ctrl->wValue >> 8) {
+ switch (w_value >> 8) {
case USB_DT_DEVICE:
- value = min (ctrl->wLength, (u16) sizeof *dev->dev);
+ value = min (w_length, (u16) sizeof *dev->dev);
req->buf = dev->dev;
break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!dev->hs_config)
break;
- value = min (ctrl->wLength, (u16)
+ value = min (w_length, (u16)
sizeof (struct usb_qualifier_descriptor));
make_qualifier (dev);
break;
#endif
case USB_DT_CONFIG:
value = config_buf (dev,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff);
+ w_value >> 8,
+ w_value & 0xff);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (w_length, (u16) value);
break;
case USB_DT_STRING:
goto unrecognized;
case USB_REQ_SET_CONFIGURATION:
if (ctrl->bRequestType != 0)
break;
- if (0 == (u8) ctrl->wValue) {
+ if (0 == (u8) w_value) {
value = 0;
dev->current_config = 0;
usb_gadget_vbus_draw(gadget, 8 /* mA */ );
// user mode expected to disable endpoints
} else {
u8 config, power;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH) {
config = dev->hs_config->bConfigurationValue;
power = dev->hs_config->bMaxPower;
power = dev->config->bMaxPower;
}
- if (config == (u8) ctrl->wValue) {
+ if (config == (u8) w_value) {
value = 0;
dev->current_config = config;
usb_gadget_vbus_draw(gadget, 2 * power);
if (ctrl->bRequestType != 0x80)
break;
*(u8 *)req->buf = dev->current_config;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (w_length, (u16) 1);
break;
#endif
VDEBUG (dev, "%s req%02x.%02x v%04x i%04x l%d\n",
dev->usermode_setup ? "delegate" : "fail",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ w_value, le16_to_cpu(ctrl->wIndex), w_length);
/* if there's an ep0 reader, don't stall */
if (dev->usermode_setup) {
delegate:
dev->setup_in = (ctrl->bRequestType & USB_DIR_IN)
? 1 : 0;
+ dev->setup_wLength = w_length;
dev->setup_out_ready = 0;
dev->setup_out_error = 0;
value = 0;
/* read DATA stage for OUT right away */
- if (unlikely (!dev->setup_in && ctrl->wLength)) {
+ if (unlikely (!dev->setup_in && w_length)) {
value = setup_req (gadget->ep0, dev->req,
- ctrl->wLength);
+ w_length);
if (value < 0)
break;
value = usb_ep_queue (gadget->ep0, dev->req,
/* proceed with data transfer and status phases? */
if (value >= 0 && dev->state != STATE_SETUP) {
req->length = value;
- req->zero = value < ctrl->wLength
- && (value % gadget->ep0->maxpacket) == 0;
+ req->zero = value < w_length;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value);
spin_unlock_irq (&dev->lock);
/* break link to dcache */
- down (&parent->i_sem);
+ mutex_lock (&parent->i_mutex);
d_delete (dentry);
dput (dentry);
- up (&parent->i_sem);
+ mutex_unlock (&parent->i_mutex);
/* fds may still be open */
goto restart;
static struct inode *
gadgetfs_create_file (struct super_block *sb, char const *name,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
struct dentry **dentry_p);
static int activate_ep_files (struct dev_data *dev)
gadget_for_each_ep (ep, dev->gadget) {
struct ep_data *data;
- data = kmalloc (sizeof *data, GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
goto enomem;
- memset (data, 0, sizeof data);
data->state = STATE_EP_DISABLED;
init_MUTEX (&data->lock);
init_waitqueue_head (&data->wait);
data, &ep_config_operations,
&data->dentry);
if (!data->inode) {
+ usb_ep_free_request(ep, data->req);
kfree (data);
goto enomem;
}
}
static struct usb_gadget_driver gadgetfs_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH,
#else
.speed = USB_SPEED_FULL,
.driver = {
.name = (char *) shortname,
- // .shutdown = ...
- // .suspend = ...
- // .resume = ...
},
};
static struct inode *
gadgetfs_make_inode (struct super_block *sb,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
int mode)
{
struct inode *inode = new_inode (sb);
*/
static struct inode *
gadgetfs_create_file (struct super_block *sb, char const *name,
- void *data, struct file_operations *fops,
+ void *data, const struct file_operations *fops,
struct dentry **dentry_p)
{
struct dentry *dentry;
struct inode *inode;
- struct qstr qname;
- qname.name = name;
- qname.len = strlen (name);
- qname.hash = full_name_hash (qname.name, qname.len);
- dentry = d_alloc (sb->s_root, &qname);
+ dentry = d_alloc_name(sb->s_root, name);
if (!dentry)
return NULL;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = GADGETFS_MAGIC;
sb->s_op = &gadget_fs_operations;
+ sb->s_time_gran = 1;
/* root inode */
inode = gadgetfs_make_inode (sb,