[PATCH 13/23] libusbg: Add return value to gadget creation functions.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Functions related to gadget creation should return error codes
instead of pointer.

Signed-off-by: Krzysztof Opasiak <k.opasiak@xxxxxxxxxxx>
---
 examples/gadget-acm-ecm.c |    4 +-
 include/usbg/usbg.h       |   21 ++--
 src/usbg.c                |  258 +++++++++++++++++++++++++++++----------------
 3 files changed, 185 insertions(+), 98 deletions(-)

diff --git a/examples/gadget-acm-ecm.c b/examples/gadget-acm-ecm.c
index 5ab42cf..b1131b4 100644
--- a/examples/gadget-acm-ecm.c
+++ b/examples/gadget-acm-ecm.c
@@ -63,8 +63,8 @@ int main(void)
 		goto out1;
 	}
 
-	g = usbg_create_gadget(s, "g1", &g_attrs, &g_strs);
-	if (!g) {
+	usbg_ret = usbg_create_gadget(s, "g1", &g_attrs, &g_strs, &g);
+	if (usbg_ret != USBG_SUCCESS) {
 		fprintf(stderr, "Error on create gadget\n");
 		goto out2;
 	}
diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h
index 0d76010..f6f7a2e 100644
--- a/include/usbg/usbg.h
+++ b/include/usbg/usbg.h
@@ -186,6 +186,7 @@ typedef enum  {
 	USBG_ERROR_INVALID_PARAM = -3,
 	USBG_ERROR_NOT_FOUND = -4,
 	USBG_ERROR_IO = -5,
+	USBG_ERROR_EXIST = -6,
 	USBG_ERROR_OTHER_ERROR = -99
 } usbg_error;
 
@@ -255,10 +256,11 @@ extern usbg_config *usbg_get_config(usbg_gadget *g, const char *name);
  * @param name Name of the gadget
  * @param idVendor Gadget vendor ID
  * @param idProduct Gadget product ID
- * @return Pointer to gadget or NULL if the gadget cannot be created
+ * @param g Pointer to be filled with pointer to gadget
+ * @return 0 on success usbg_error if error occurred
  */
-extern usbg_gadget *usbg_create_gadget_vid_pid(usbg_state *s, char *name,
-		uint16_t idVendor, uint16_t idProduct);
+extern int usbg_create_gadget_vid_pid(usbg_state *s, char *name,
+		uint16_t idVendor, uint16_t idProduct, usbg_gadget **g);
 
 /**
  * @brief Create a new USB gadget device and set given attributes
@@ -267,18 +269,20 @@ extern usbg_gadget *usbg_create_gadget_vid_pid(usbg_state *s, char *name,
  * @param name Name of the gadget
  * @param g_attrs Gadget attributes to be set. If NULL setting is omitted.
  * @param g_strs Gadget strings to be set. If NULL setting is omitted.
+ * @param g Pointer to be filled with pointer to gadget
  * @note Given strings are assumed to be in US English
- * @return Pointer to gadget or NULL if the gadget cannot be created
+ * @return 0 on success usbg_error if error occurred
  */
-extern usbg_gadget *usbg_create_gadget(usbg_state *s, char *name,
-		usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs);
+extern int usbg_create_gadget(usbg_state *s, char *name,
+		usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, usbg_gadget **g);
 
 /**
  * @brief Set the USB gadget attributes
  * @param g Pointer to gadget
  * @param g_attrs Gadget attributes
+ * @return 0 on success usbg_error if error occurred
  */
-extern void usbg_set_gadget_attrs(usbg_gadget *g,
+extern int usbg_set_gadget_attrs(usbg_gadget *g,
 		usbg_gadget_attrs *g_attrs);
 
 /**
@@ -383,8 +387,9 @@ extern usbg_gadget_strs *usbg_get_gadget_strs(usbg_gadget *g, int lang,
  * @param g Pointer to gadget
  * @param lang USB language ID
  * @param g_sttrs Gadget attributes
+ * @return 0 on success usbg_error if error occurred
  */
-extern void usbg_set_gadget_strs(usbg_gadget *g, int lang,
+extern int usbg_set_gadget_strs(usbg_gadget *g, int lang,
 		usbg_gadget_strs *g_strs);
 
 /**
diff --git a/src/usbg.c b/src/usbg.c
index d5c36c9..0a469cd 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -142,6 +142,7 @@ static int usbg_translate_error(int error)
 		ret = USBG_ERROR_NO_MEM;
 		break;
 	case EACCES:
+	case EROFS:
 		ret = USBG_ERROR_NO_ACCESS;
 		break;
 	case ENOENT:
@@ -155,6 +156,9 @@ static int usbg_translate_error(int error)
 	case EIO:
 		ret = USBG_ERROR_IO;
 		break;
+	case EEXIST:
+		ret = USBG_ERROR_EXIST;
+		break;
 	default:
 		ret = USBG_ERROR_OTHER_ERROR;
 	}
@@ -261,46 +265,49 @@ static int usbg_read_string(char *path, char *name, char *file, char *buf)
 	return ret;
 }
 
-static void usbg_write_buf(char *path, char *name, char *file, char *buf)
+static int usbg_write_buf(char *path, char *name, char *file, char *buf)
 {
 	char p[USBG_MAX_STR_LENGTH];
 	FILE *fp;
-	int err;
+	int ret = USBG_SUCCESS;
 
 	sprintf(p, "%s/%s/%s", path, name, file);
 
 	fp = fopen(p, "w");
-	if (!fp) {
-		ERRORNO("%s\n", p);
-		return;
-	}
+	if (fp) {
+		fputs(buf, fp);
+		fflush(fp);
 
-	fputs(buf, fp);
-	fflush(fp);
-	err = ferror(fp);
-	fclose(fp);
-	
-	if (err){
-		ERROR("write error");
-		return;
+		ret = ferror(fp);
+		if (ret)
+			ret = usbg_translate_error(errno);
+
+		fclose(fp);
+	} else {
+		/* Set error correctly */
+		ret = usbg_translate_error(errno);
 	}
+
+	return ret;
 }
 
-static void usbg_write_int(char *path, char *name, char *file, int value, char *str)
+static int usbg_write_int(char *path, char *name, char *file, int value,
+		char *str)
 {
 	char buf[USBG_MAX_STR_LENGTH];
 
 	sprintf(buf, str, value);
-	usbg_write_buf(path, name, file, buf);
+	return usbg_write_buf(path, name, file, buf);
 }
 
 #define usbg_write_dec(p, n, f, v)	usbg_write_int(p, n, f, v, "%d\n")
 #define usbg_write_hex16(p, n, f, v)	usbg_write_int(p, n, f, v, "0x%04x\n")
 #define usbg_write_hex8(p, n, f, v)	usbg_write_int(p, n, f, v, "0x%02x\n")
 
-static inline void usbg_write_string(char *path, char *name, char *file, char *buf)
+static inline int usbg_write_string(char *path, char *name, char *file,
+		char *buf)
 {
-	usbg_write_buf(path, name, file, buf);
+	return usbg_write_buf(path, name, file, buf);
 }
 
 static inline void usbg_free_binding(usbg_binding *b)
@@ -806,96 +813,112 @@ usbg_binding *usbg_get_link_binding(usbg_config *c, usbg_function *f)
 	return NULL;
 }
 
-static usbg_gadget *usbg_create_empty_gadget(usbg_state *s, char *name)
+static int usbg_create_empty_gadget(usbg_state *s, char *name, usbg_gadget **g)
 {
 	char gpath[USBG_MAX_PATH_LENGTH];
-	usbg_gadget *g;
-	int ret;
+	int ret = USBG_SUCCESS;
 
 	sprintf(gpath, "%s/%s", s->path, name);
 
-	g = malloc(sizeof(usbg_gadget));
-	if (!g) {
-		ERRORNO("allocating gadget\n");
-		return NULL;
-	}
-
-	TAILQ_INIT(&g->configs);
-	TAILQ_INIT(&g->functions);
-	strcpy(g->name, name);
-	strcpy(g->path, s->path);
-	g->parent = s;
+	*g = malloc(sizeof(usbg_gadget));
+	if (*g) {
+		usbg_gadget *gad = *g; /* alias only */
+
+		TAILQ_INIT(&gad->configs);
+		TAILQ_INIT(&gad->functions);
+		strcpy(gad->name, name);
+		strcpy(gad->path, s->path);
+		gad->parent = s;
+
+		ret = mkdir(gpath, S_IRWXU|S_IRWXG|S_IRWXO);
+		if (ret == 0) {
+			/* Should be empty but read the default */
+			ret = usbg_read_string(gad->path, gad->name, "UDC",
+				 gad->udc);
+			if (ret != USBG_SUCCESS)
+				rmdir(gpath);
+		} else {
+			ret = usbg_translate_error(errno);
+		}
 
-	ret = mkdir(gpath, S_IRWXU|S_IRWXG|S_IRWXO);
-	if (ret < 0) {
-		ERRORNO("%s\n", gpath);
-		free(g);
-		return NULL;
+		if (ret != USBG_SUCCESS) {
+			free(gad);
+			*g = NULL;
+		}
+	} else {
+		ret = USBG_ERROR_NO_MEM;
 	}
 
-	/* Should be empty but read the default */
-	usbg_read_string(g->path, g->name, "UDC", g->udc);
-
-	return g;
+	return ret;
 }
 
-
-
-usbg_gadget *usbg_create_gadget_vid_pid(usbg_state *s, char *name,
-		uint16_t idVendor, uint16_t idProduct)
+int usbg_create_gadget_vid_pid(usbg_state *s, char *name,
+		uint16_t idVendor, uint16_t idProduct, usbg_gadget **g)
 {
-	usbg_gadget *g;
+	int ret;
+	usbg_gadget *gad;
 
-	if (!s)
-		return NULL;
+	if (!s || !g)
+		return USBG_ERROR_INVALID_PARAM;
 
-	g = usbg_get_gadget(s, name);
-	if (g) {
+	gad = usbg_get_gadget(s, name);
+	if (gad) {
 		ERROR("duplicate gadget name\n");
-		return NULL;
+		return USBG_ERROR_EXIST;
 	}
 
-	g = usbg_create_empty_gadget(s, name);
+	ret = usbg_create_empty_gadget(s, name, g);
+	gad = *g;
 
 	/* Check if gadget creation was successful and set attributes */
-	if (g) {
-		usbg_write_hex16(s->path, name, "idVendor", idVendor);
-		usbg_write_hex16(s->path, name, "idProduct", idProduct);
-
-		INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, name, g, gnode);
+	if (ret == USBG_SUCCESS) {
+		if ((ret = usbg_write_hex16(s->path, name, "idVendor", idVendor))
+				== USBG_SUCCESS
+				&&
+		(ret = usbg_write_hex16(s->path, name, "idProduct", idProduct))
+				== USBG_SUCCESS)
+			INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, name,
+				 gad, gnode);
+		else
+			usbg_free_gadget(gad);
 	}
 
-	return g;
+	return ret;
 }
 
-usbg_gadget *usbg_create_gadget(usbg_state *s, char *name,
-		usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs)
+int usbg_create_gadget(usbg_state *s, char *name,
+		usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, usbg_gadget **g)
 {
-	usbg_gadget *g;
+	usbg_gadget *gad;
+	int ret;
 
-	if (!s)
-		return NULL;
+	if (!s || !g)
+			return USBG_ERROR_INVALID_PARAM;
 
-	g = usbg_get_gadget(s, name);
-	if (g) {
+	gad = usbg_get_gadget(s, name);
+	if (gad) {
 		ERROR("duplicate gadget name\n");
-		return NULL;
+		return USBG_ERROR_EXIST;
 	}
 
-	g = usbg_create_empty_gadget(s, name);
+	ret = usbg_create_empty_gadget(s, name, g);
+	gad = *g;
 
 	/* Check if gadget creation was successful and set attrs and strings */
-	if (g) {
+	if (ret == USBG_SUCCESS) {
 		if (g_attrs)
-			usbg_set_gadget_attrs(g, g_attrs);
+			ret = usbg_set_gadget_attrs(gad, g_attrs);
 
 		if (g_strs)
-			usbg_set_gadget_strs(g, LANG_US_ENG, g_strs);
+			ret = usbg_set_gadget_strs(gad, LANG_US_ENG, g_strs);
 
-		INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, name, g, gnode);
+		if (ret == USBG_SUCCESS)
+			INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, name,
+				gad, gnode);
+		else
+			usbg_free_gadget(gad);
 	}
-
-	return g;
+	return ret;
 }
 
 usbg_gadget_attrs *usbg_get_gadget_attrs(usbg_gadget *g,
@@ -941,19 +964,51 @@ int usbg_get_gadget_udc(usbg_gadget *g, char *buf, size_t len)
 	return ret;
 }
 
-void usbg_set_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs)
+int usbg_set_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs)
 {
+	int ret;
 	if (!g || !g_attrs)
-		return;
+		return USBG_ERROR_INVALID_PARAM;
+
+	ret = usbg_write_hex16(g->path, g->name, "bcdUSB", g_attrs->bcdUSB);
+	if (ret != USBG_SUCCESS)
+		goto out;
+
+	ret = usbg_write_hex8(g->path, g->name, "bDeviceClass",
+		g_attrs->bDeviceClass);
+	if (ret != USBG_SUCCESS)
+			goto out;
+
+	ret = usbg_write_hex8(g->path, g->name, "bDeviceSubClass",
+		g_attrs->bDeviceSubClass);
+	if (ret != USBG_SUCCESS)
+			goto out;
+
+	ret = usbg_write_hex8(g->path, g->name, "bDeviceProtocol",
+		g_attrs->bDeviceProtocol);
+	if (ret != USBG_SUCCESS)
+			goto out;
 
-	usbg_write_hex16(g->path, g->name, "bcdUSB", g_attrs->bcdUSB);
-	usbg_write_hex8(g->path, g->name, "bDeviceClass", g_attrs->bDeviceClass);
-	usbg_write_hex8(g->path, g->name, "bDeviceSubClass", g_attrs->bDeviceSubClass);
-	usbg_write_hex8(g->path, g->name, "bDeviceProtocol", g_attrs->bDeviceProtocol);
-	usbg_write_hex8(g->path, g->name, "bMaxPacketSize0", g_attrs->bMaxPacketSize0);
-	usbg_write_hex16(g->path, g->name, "idVendor", g_attrs->idVendor);
-	usbg_write_hex16(g->path, g->name, "idProduct", g_attrs->idProduct);
-	usbg_write_hex16(g->path, g->name, "bcdDevice", g_attrs->bcdDevice);
+	ret = usbg_write_hex8(g->path, g->name, "bMaxPacketSize0",
+		g_attrs->bMaxPacketSize0);
+	if (ret != USBG_SUCCESS)
+			goto out;
+
+	ret = usbg_write_hex16(g->path, g->name, "idVendor",
+		g_attrs->idVendor);
+	if (ret != USBG_SUCCESS)
+			goto out;
+
+	ret = usbg_write_hex16(g->path, g->name, "idProduct",
+		 g_attrs->idProduct);
+	if (ret != USBG_SUCCESS)
+			goto out;
+
+	ret = usbg_write_hex16(g->path, g->name, "bcdDevice",
+		g_attrs->bcdDevice);
+
+out:
+	return ret;
 }
 
 void usbg_set_gadget_vendor_id(usbg_gadget *g, uint16_t idVendor)
@@ -1007,18 +1062,45 @@ usbg_gadget_strs *usbg_get_gadget_strs(usbg_gadget *g, int lang,
 	return g_strs;
 }
 
-void usbg_set_gadget_strs(usbg_gadget *g, int lang,
+static int usbg_check_dir(char *path)
+{
+	int ret = USBG_SUCCESS;
+	DIR *dir;
+
+	/* Assume that user will always have read access to this directory */
+	dir = opendir(path);
+	if (dir)
+		closedir(dir);
+	else if (errno != ENOENT || mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO) != 0)
+		ret = usbg_translate_error(errno);
+
+	return ret;
+}
+
+int usbg_set_gadget_strs(usbg_gadget *g, int lang,
 		usbg_gadget_strs *g_strs)
 {
 	char path[USBG_MAX_PATH_LENGTH];
+	DIR *dir;
+	int ret = USBG_SUCCESS;
 
 	sprintf(path, "%s/%s/%s/0x%x", g->path, g->name, STRINGS_DIR, lang);
 
-	mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO);
+	ret = usbg_check_dir(path);
+	if (ret == USBG_SUCCESS) {
+		ret = usbg_write_string(path, "", "serialnumber", g_strs->str_ser);
+		if (ret != USBG_SUCCESS)
+			goto out;
 
-	usbg_write_string(path, "", "serialnumber", g_strs->str_ser);
-	usbg_write_string(path, "", "manufacturer", g_strs->str_mnf);
-	usbg_write_string(path, "", "product", g_strs->str_prd);
+		ret = usbg_write_string(path, "", "manufacturer", g_strs->str_mnf);
+		if (ret != USBG_SUCCESS)
+			goto out;
+
+		ret = usbg_write_string(path, "", "product", g_strs->str_prd);
+	}
+
+out:
+	return ret;
 }
 
 void usbg_set_gadget_serial_number(usbg_gadget *g, int lang, char *serno)
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux