xref: /openbmc/linux/drivers/usb/gadget/u_f.h (revision bfd08d06)
15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21efd54eaSAndrzej Pietrasiewicz /*
31efd54eaSAndrzej Pietrasiewicz  * u_f.h
41efd54eaSAndrzej Pietrasiewicz  *
51efd54eaSAndrzej Pietrasiewicz  * Utility definitions for USB functions
61efd54eaSAndrzej Pietrasiewicz  *
71efd54eaSAndrzej Pietrasiewicz  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
81efd54eaSAndrzej Pietrasiewicz  *		http://www.samsung.com
91efd54eaSAndrzej Pietrasiewicz  *
101b4a3b51SAndrzej Pietrasiewicz  * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
111efd54eaSAndrzej Pietrasiewicz  */
121efd54eaSAndrzej Pietrasiewicz 
131efd54eaSAndrzej Pietrasiewicz #ifndef __U_F_H__
141efd54eaSAndrzej Pietrasiewicz #define __U_F_H__
151efd54eaSAndrzej Pietrasiewicz 
16079fe5a6SFelipe F. Tonello #include <linux/usb/gadget.h>
17b1cd1b65SBrooke Basile #include <linux/overflow.h>
18079fe5a6SFelipe F. Tonello 
1974d48466SAndrzej Pietrasiewicz /* Variable Length Array Macros **********************************************/
2074d48466SAndrzej Pietrasiewicz #define vla_group(groupname) size_t groupname##__next = 0
2174d48466SAndrzej Pietrasiewicz #define vla_group_size(groupname) groupname##__next
2274d48466SAndrzej Pietrasiewicz 
2374d48466SAndrzej Pietrasiewicz #define vla_item(groupname, type, name, n) \
2474d48466SAndrzej Pietrasiewicz 	size_t groupname##_##name##__offset = ({			       \
25b1cd1b65SBrooke Basile 		size_t offset = 0;					       \
26b1cd1b65SBrooke Basile 		if (groupname##__next != SIZE_MAX) {			       \
2774d48466SAndrzej Pietrasiewicz 			size_t align_mask = __alignof__(type) - 1;	       \
28b1cd1b65SBrooke Basile 			size_t size = array_size(n, sizeof(type));	       \
29*bfd08d06SAndy Shevchenko 			offset = (groupname##__next + align_mask) &	       \
30*bfd08d06SAndy Shevchenko 				  ~align_mask;				       \
31b1cd1b65SBrooke Basile 			if (check_add_overflow(offset, size,		       \
32b1cd1b65SBrooke Basile 					       &groupname##__next)) {          \
33b1cd1b65SBrooke Basile 				groupname##__next = SIZE_MAX;		       \
34b1cd1b65SBrooke Basile 				offset = 0;				       \
35b1cd1b65SBrooke Basile 			}						       \
36b1cd1b65SBrooke Basile 		}							       \
3774d48466SAndrzej Pietrasiewicz 		offset;							       \
3874d48466SAndrzej Pietrasiewicz 	})
3974d48466SAndrzej Pietrasiewicz 
4074d48466SAndrzej Pietrasiewicz #define vla_item_with_sz(groupname, type, name, n) \
41b1cd1b65SBrooke Basile 	size_t groupname##_##name##__sz = array_size(n, sizeof(type));	        \
4274d48466SAndrzej Pietrasiewicz 	size_t groupname##_##name##__offset = ({			        \
43b1cd1b65SBrooke Basile 		size_t offset = 0;						\
44b1cd1b65SBrooke Basile 		if (groupname##__next != SIZE_MAX) {				\
4574d48466SAndrzej Pietrasiewicz 			size_t align_mask = __alignof__(type) - 1;		\
46*bfd08d06SAndy Shevchenko 			offset = (groupname##__next + align_mask) &		\
47*bfd08d06SAndy Shevchenko 				  ~align_mask;					\
48b1cd1b65SBrooke Basile 			if (check_add_overflow(offset, groupname##_##name##__sz,\
49b1cd1b65SBrooke Basile 							&groupname##__next)) {	\
50b1cd1b65SBrooke Basile 				groupname##__next = SIZE_MAX;			\
51b1cd1b65SBrooke Basile 				offset = 0;					\
52b1cd1b65SBrooke Basile 			}							\
53b1cd1b65SBrooke Basile 		}								\
5474d48466SAndrzej Pietrasiewicz 		offset;								\
5574d48466SAndrzej Pietrasiewicz 	})
5674d48466SAndrzej Pietrasiewicz 
5774d48466SAndrzej Pietrasiewicz #define vla_ptr(ptr, groupname, name) \
5874d48466SAndrzej Pietrasiewicz 	((void *) ((char *)ptr + groupname##_##name##__offset))
5974d48466SAndrzej Pietrasiewicz 
601efd54eaSAndrzej Pietrasiewicz struct usb_ep;
611efd54eaSAndrzej Pietrasiewicz struct usb_request;
621efd54eaSAndrzej Pietrasiewicz 
63e0466156SFelipe F. Tonello /**
64e0466156SFelipe F. Tonello  * alloc_ep_req - returns a usb_request allocated by the gadget driver and
65e0466156SFelipe F. Tonello  * allocates the request's buffer.
66e0466156SFelipe F. Tonello  *
67e0466156SFelipe F. Tonello  * @ep: the endpoint to allocate a usb_request
68e0466156SFelipe F. Tonello  * @len: usb_requests's buffer suggested size
69e0466156SFelipe F. Tonello  *
70e0466156SFelipe F. Tonello  * In case @ep direction is OUT, the @len will be aligned to ep's
71e0466156SFelipe F. Tonello  * wMaxPacketSize. In order to avoid memory leaks or drops, *always* use
72e0466156SFelipe F. Tonello  * usb_requests's length (req->length) to refer to the allocated buffer size.
73e0466156SFelipe F. Tonello  * Requests allocated via alloc_ep_req() *must* be freed by free_ep_req().
74e0466156SFelipe F. Tonello  */
75aadbe812SFelipe F. Tonello struct usb_request *alloc_ep_req(struct usb_ep *ep, size_t len);
76e0466156SFelipe F. Tonello 
77e0466156SFelipe F. Tonello /* Frees a usb_request previously allocated by alloc_ep_req() */
free_ep_req(struct usb_ep * ep,struct usb_request * req)78079fe5a6SFelipe F. Tonello static inline void free_ep_req(struct usb_ep *ep, struct usb_request *req)
79079fe5a6SFelipe F. Tonello {
807fafcfdfSYavuz, Tuba 	WARN_ON(req->buf == NULL);
81079fe5a6SFelipe F. Tonello 	kfree(req->buf);
827fafcfdfSYavuz, Tuba 	req->buf = NULL;
83079fe5a6SFelipe F. Tonello 	usb_ep_free_request(ep, req);
84079fe5a6SFelipe F. Tonello }
851efd54eaSAndrzej Pietrasiewicz 
861efd54eaSAndrzej Pietrasiewicz #endif /* __U_F_H__ */
87