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