1 /* Aravis - Digital camera library
2  *
3  * Copyright © 2009-2016 Emmanuel Pacaud
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * Author: Emmanuel Pacaud <emmanuel@gnome.org>
21  */
22 
23 /**
24  * SECTION: arvuvcp
25  * @short_description: USB3Vision control packet handling
26  */
27 
28 #include <arvuvcp.h>
29 #include <arvenumtypes.h>
30 #include <arvdebug.h>
31 #include <arvstr.h>
32 #include <string.h>
33 
34 void
arv_uvcp_packet_free(ArvUvcpPacket * packet)35 arv_uvcp_packet_free (ArvUvcpPacket *packet)
36 {
37 	g_free (packet);
38 }
39 
40 /**
41  * arv_uvcp_packet_new_read_memory_cmd: (skip)
42  * @address: read address
43  * @size: read size, in bytes
44  * @packet_id: packet id
45  * @packet_size: (out): packet size, in bytes
46  * Return value: (transfer full): a new #ArvUvcpPacket
47  *
48  * Create a uvcp packet for a memory read command.
49  */
50 
51 ArvUvcpPacket *
arv_uvcp_packet_new_read_memory_cmd(guint64 address,guint32 size,guint16 packet_id,size_t * packet_size)52 arv_uvcp_packet_new_read_memory_cmd (guint64 address, guint32 size, guint16 packet_id, size_t *packet_size)
53 {
54 	ArvUvcpReadMemoryCmd *packet;
55 
56 	g_return_val_if_fail (packet_size != NULL, NULL);
57 
58 	*packet_size = sizeof (ArvUvcpReadMemoryCmd);
59 
60 	packet = g_malloc (*packet_size);
61 
62 	packet->header.magic = GUINT32_TO_LE (ARV_UVCP_MAGIC);
63 	packet->header.packet_type = GUINT16_TO_LE (ARV_UVCP_PACKET_TYPE_CMD);
64 	packet->header.command = GUINT16_TO_LE (ARV_UVCP_COMMAND_READ_MEMORY_CMD);
65 	packet->header.size = GUINT16_TO_LE (sizeof (ArvUvcpReadMemoryCmdInfos));
66 	packet->header.id = GUINT16_TO_LE (packet_id);
67 	packet->infos.address = GUINT64_TO_LE (address);
68 	packet->infos.size = GUINT16_TO_LE (size);
69 
70 	return (ArvUvcpPacket *) packet;
71 }
72 
73 /**
74  * arv_uvcp_packet_new_write_memory_cmd: (skip)
75  * @address: write address
76  * @size: write size, in bytes
77  * @packet_id: packet id
78  * @packet_size: (out): packet size, in bytes
79  * Return value: (transfer full): a new #ArvUvcpPacket
80  *
81  * Create a uvcp packet for a memory write command.
82  */
83 
84 ArvUvcpPacket *
arv_uvcp_packet_new_write_memory_cmd(guint64 address,guint32 size,guint16 packet_id,size_t * packet_size)85 arv_uvcp_packet_new_write_memory_cmd (guint64 address, guint32 size, guint16 packet_id, size_t *packet_size)
86 {
87 	ArvUvcpWriteMemoryCmd *packet;
88 
89 	g_return_val_if_fail (packet_size != NULL, NULL);
90 
91 	*packet_size = sizeof (ArvUvcpWriteMemoryCmd) + size;
92 
93 	packet = g_malloc (*packet_size);
94 
95 	packet->header.magic = GUINT32_TO_LE (ARV_UVCP_MAGIC);
96 	packet->header.packet_type = GUINT16_TO_LE (ARV_UVCP_PACKET_TYPE_CMD);
97 	packet->header.command = GUINT16_TO_LE (ARV_UVCP_COMMAND_WRITE_MEMORY_CMD);
98 	packet->header.size = GUINT16_TO_LE (sizeof (ArvUvcpWriteMemoryCmdInfos) + size);
99 	packet->header.id = GUINT16_TO_LE (packet_id);
100 	packet->infos.address = GUINT64_TO_LE (address);
101 
102 	return (ArvUvcpPacket *) packet;
103 }
104 
105 static const char *
arv_enum_to_string(GType type,guint enum_value)106 arv_enum_to_string (GType type,
107 		    guint enum_value)
108 {
109 	GEnumClass *enum_class;
110 	GEnumValue *value;
111 	const char *retval = NULL;
112 
113 	enum_class = g_type_class_ref (type);
114 
115 	value = g_enum_get_value (enum_class, enum_value);
116 	if (value)
117 		retval = value->value_nick;
118 
119 	g_type_class_unref (enum_class);
120 
121 	return retval;
122 }
123 
124 const char *
arv_uvcp_packet_type_to_string(ArvUvcpPacketType value)125 arv_uvcp_packet_type_to_string (ArvUvcpPacketType value)
126 {
127 	return arv_enum_to_string (ARV_TYPE_UVCP_PACKET_TYPE, value);
128 }
129 
130 const char *
arv_uvcp_command_to_string(ArvUvcpCommand value)131 arv_uvcp_command_to_string (ArvUvcpCommand value)
132 {
133 	return arv_enum_to_string (ARV_TYPE_UVCP_COMMAND, value);
134 }
135 
136 /**
137  * arv_uvcp_packet_to_string:
138  * @packet: a #ArvUvcpPacket
139  *
140  * Converts @packet into a human readable string.
141  *
142  * return value: (transfer full): A newly allocated string.
143  */
144 
145 char *
arv_uvcp_packet_to_string(const ArvUvcpPacket * packet)146 arv_uvcp_packet_to_string (const ArvUvcpPacket *packet)
147 {
148 	GString *string;
149 	char *c_string;
150 	int packet_size;
151 	guint64 value;
152 
153 	g_return_val_if_fail (packet != NULL, NULL);
154 
155 	string = g_string_new ("");
156 
157 	g_string_append_printf (string, "packet_type  = %s\n",
158 				arv_uvcp_packet_type_to_string (GUINT16_FROM_LE (packet->header.packet_type)));
159 	g_string_append_printf (string, "command      = %s\n",
160 				arv_uvcp_command_to_string (GUINT16_FROM_LE (packet->header.command)));
161 	g_string_append_printf (string, "size         = %d\n", GUINT16_FROM_LE (packet->header.size));
162 	g_string_append_printf (string, "id           = %d\n", GUINT16_FROM_LE (packet->header.id));
163 
164 	switch (GUINT16_FROM_LE (packet->header.command)) {
165 		case ARV_UVCP_COMMAND_READ_MEMORY_CMD:
166 			{
167 				ArvUvcpReadMemoryCmd *cmd_packet = (void *) packet;
168 
169 				value = GUINT64_FROM_LE (cmd_packet->infos.address);
170 				g_string_append_printf (string, "address      = 0x%016lx\n", value);
171 				value = GUINT16_FROM_LE (cmd_packet->infos.size);
172 				g_string_append_printf (string, "size         = %10lu (0x%08lx)\n",
173 							value, value);
174 				break;
175 			}
176 		case ARV_UVCP_COMMAND_READ_MEMORY_ACK:
177 			{
178 				break;
179 			}
180 		case ARV_UVCP_COMMAND_WRITE_MEMORY_CMD:
181 			{
182 				ArvUvcpWriteMemoryCmd *cmd_packet = (void *) packet;
183 
184 				value = GUINT64_FROM_LE (cmd_packet->infos.address);
185 				g_string_append_printf (string, "address      = 0x%016lx\n", value);
186 				break;
187 			}
188 		case ARV_UVCP_COMMAND_WRITE_MEMORY_ACK:
189 			{
190 				ArvUvcpWriteMemoryAck *cmd_packet = (void *) packet;
191 
192 				value = GUINT64_FROM_LE (cmd_packet->infos.bytes_written);
193 				g_string_append_printf (string, "written      = %10lu (0x%08lx)\n",
194 							value, value);
195 				break;
196 			}
197 	}
198 
199 	packet_size = sizeof (ArvUvcpHeader) + GUINT16_FROM_LE (packet->header.size);
200 
201 	arv_g_string_append_hex_dump (string, packet, packet_size);
202 
203 	c_string = string->str;
204 
205 	g_string_free (string, FALSE);
206 
207 	return c_string;
208 }
209 
210 /**
211  * arv_uvcp_packet_debug:
212  * @packet: a #ArvUvcpPacket
213  * @level: debug level
214  *
215  * Dumps the content of @packet if level is lower or equal to the current debug level for the cp debug category. See arv_debug_enable().
216  */
217 
218 void
arv_uvcp_packet_debug(const ArvUvcpPacket * packet,ArvDebugLevel level)219 arv_uvcp_packet_debug (const ArvUvcpPacket *packet, ArvDebugLevel level)
220 {
221 	char *string;
222 
223 	if (!arv_debug_check (&arv_debug_category_cp, level))
224 		return;
225 
226 	string = arv_uvcp_packet_to_string (packet);
227 	switch (level) {
228 		case ARV_DEBUG_LEVEL_LOG:
229 			arv_log_cp ("%s", string);
230 			break;
231 		case ARV_DEBUG_LEVEL_DEBUG:
232 			arv_debug_cp ("%s", string);
233 			break;
234 		case ARV_DEBUG_LEVEL_WARNING:
235 			arv_warning_cp ("%s", string);
236 			break;
237 		default:
238 			break;
239 	}
240 	g_free (string);
241 }
242