Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: raw-gadget: report suspend, resume, reset, and disconnect events

Update USB_RAW_IOCTL_EVENT_FETCH to also report suspend, resume, reset,
and disconnect events.

This allows the code that emulates a USB device via Raw Gadget to handle
these events. For example, the device can restart enumeration when it
gets reset.

Also do not print a WARNING when the event queue overflows. With these new
events being queued, the queue might overflow if the device emulation code
stops fetching events.

Also print debug messages when a non-control event is received.

Signed-off-by: Andrey Konovalov <andreyknvl@gmail.com>
Link: https://lore.kernel.org/r/d610b629a5f32fb76c24012180743f7f0f1872c0.1698350424.git.andreyknvl@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Andrey Konovalov and committed by
Greg Kroah-Hartman
c3a383d8 1f97e3f4

+56 -10
+44 -8
drivers/usb/gadget/legacy/raw_gadget.c
··· 65 65 struct usb_raw_event *event; 66 66 67 67 spin_lock_irqsave(&queue->lock, flags); 68 - if (WARN_ON(queue->size >= RAW_EVENT_QUEUE_SIZE)) { 68 + if (queue->size >= RAW_EVENT_QUEUE_SIZE) { 69 69 spin_unlock_irqrestore(&queue->lock, flags); 70 70 return -ENOMEM; 71 71 } ··· 311 311 dev->eps_num = i; 312 312 spin_unlock_irqrestore(&dev->lock, flags); 313 313 314 + dev_dbg(&gadget->dev, "gadget connected\n"); 314 315 ret = raw_queue_event(dev, USB_RAW_EVENT_CONNECT, 0, NULL); 315 316 if (ret < 0) { 316 - dev_err(&gadget->dev, "failed to queue event\n"); 317 + dev_err(&gadget->dev, "failed to queue connect event\n"); 317 318 set_gadget_data(gadget, NULL); 318 319 return ret; 319 320 } ··· 359 358 360 359 ret = raw_queue_event(dev, USB_RAW_EVENT_CONTROL, sizeof(*ctrl), ctrl); 361 360 if (ret < 0) 362 - dev_err(&gadget->dev, "failed to queue event\n"); 361 + dev_err(&gadget->dev, "failed to queue control event\n"); 363 362 goto out; 364 363 365 364 out_unlock: ··· 378 377 return ret; 379 378 } 380 379 381 - /* These are currently unused but present in case UDC driver requires them. */ 382 - static void gadget_disconnect(struct usb_gadget *gadget) { } 383 - static void gadget_suspend(struct usb_gadget *gadget) { } 384 - static void gadget_resume(struct usb_gadget *gadget) { } 385 - static void gadget_reset(struct usb_gadget *gadget) { } 380 + static void gadget_disconnect(struct usb_gadget *gadget) 381 + { 382 + struct raw_dev *dev = get_gadget_data(gadget); 383 + int ret; 384 + 385 + dev_dbg(&gadget->dev, "gadget disconnected\n"); 386 + ret = raw_queue_event(dev, USB_RAW_EVENT_DISCONNECT, 0, NULL); 387 + if (ret < 0) 388 + dev_err(&gadget->dev, "failed to queue disconnect event\n"); 389 + } 390 + static void gadget_suspend(struct usb_gadget *gadget) 391 + { 392 + struct raw_dev *dev = get_gadget_data(gadget); 393 + int ret; 394 + 395 + dev_dbg(&gadget->dev, "gadget suspended\n"); 396 + ret = raw_queue_event(dev, USB_RAW_EVENT_SUSPEND, 0, NULL); 397 + if (ret < 0) 398 + dev_err(&gadget->dev, "failed to queue suspend event\n"); 399 + } 400 + static void gadget_resume(struct usb_gadget *gadget) 401 + { 402 + struct raw_dev *dev = get_gadget_data(gadget); 403 + int ret; 404 + 405 + dev_dbg(&gadget->dev, "gadget resumed\n"); 406 + ret = raw_queue_event(dev, USB_RAW_EVENT_RESUME, 0, NULL); 407 + if (ret < 0) 408 + dev_err(&gadget->dev, "failed to queue resume event\n"); 409 + } 410 + static void gadget_reset(struct usb_gadget *gadget) 411 + { 412 + struct raw_dev *dev = get_gadget_data(gadget); 413 + int ret; 414 + 415 + dev_dbg(&gadget->dev, "gadget reset\n"); 416 + ret = raw_queue_event(dev, USB_RAW_EVENT_RESET, 0, NULL); 417 + if (ret < 0) 418 + dev_err(&gadget->dev, "failed to queue reset event\n"); 419 + } 386 420 387 421 /*----------------------------------------------------------------------*/ 388 422
+12 -2
include/uapi/linux/usb/raw_gadget.h
··· 44 44 /* This event is queued when a new control request arrived to ep0. */ 45 45 USB_RAW_EVENT_CONTROL = 2, 46 46 47 + /* 48 + * These events are queued when the gadget driver is suspended, 49 + * resumed, reset, or disconnected. Note that some UDCs (e.g. dwc2) 50 + * report a disconnect event instead of a reset. 51 + */ 52 + USB_RAW_EVENT_SUSPEND = 3, 53 + USB_RAW_EVENT_RESUME = 4, 54 + USB_RAW_EVENT_RESET = 5, 55 + USB_RAW_EVENT_DISCONNECT = 6, 56 + 47 57 /* The list might grow in the future. */ 48 58 }; 49 59 ··· 64 54 * actual length of the fetched event data. 65 55 * @data: A buffer to store the fetched event data. 66 56 * 67 - * Currently the fetched data buffer is empty for USB_RAW_EVENT_CONNECT, 68 - * and contains struct usb_ctrlrequest for USB_RAW_EVENT_CONTROL. 57 + * The fetched event data buffer contains struct usb_ctrlrequest for 58 + * USB_RAW_EVENT_CONTROL and is empty for other events. 69 59 */ 70 60 struct usb_raw_event { 71 61 __u32 type;