Purely cosmetic change: add missing newline
[libam7xxx.git] / src / am7xxx.c
1 /* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs
2  *
3  * Copyright (C) 2012  Antonio Ospite <ospite@studenti.unina.it>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <libusb.h>
25
26 #include "am7xxx.h"
27 #include "serialize.h"
28
29 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
30
31 /* If we're not using GNU C, elide __attribute__
32  * taken from: http://unixwiz.net/techtips/gnu-c-attributes.html)
33  */
34 #ifndef __GNUC__
35 #  define  __attribute__(x)  /*NOTHING*/
36 #endif
37
38 static void log_message(am7xxx_context *ctx,
39                         int level,
40                         const char *function,
41                         int line,
42                         const char *fmt,
43                         ...) __attribute__ ((format (printf, 5, 6)));
44
45 #define fatal(...)        log_message(NULL, AM7XXX_LOG_FATAL,   __func__, __LINE__, __VA_ARGS__)
46 #define error(ctx, ...)   log_message(ctx,  AM7XXX_LOG_ERROR,   __func__, __LINE__, __VA_ARGS__)
47 #define warning(ctx, ...) log_message(ctx,  AM7XXX_LOG_WARNING, __func__, 0,        __VA_ARGS__)
48 #define info(ctx, ...)    log_message(ctx,  AM7XXX_LOG_INFO,    __func__, 0,        __VA_ARGS__)
49 #define debug(ctx, ...)   log_message(ctx,  AM7XXX_LOG_DEBUG,   __func__, 0,        __VA_ARGS__)
50 #define trace(ctx, ...)   log_message(ctx,  AM7XXX_LOG_TRACE,   NULL,     0,        __VA_ARGS__)
51
52 struct am7xxx_usb_device_descriptor {
53         const char *name;
54         uint16_t vendor_id;
55         uint16_t product_id;
56 };
57
58 static struct am7xxx_usb_device_descriptor supported_devices[] = {
59         {
60                 .name       = "Acer C110",
61                 .vendor_id  = 0x1de1,
62                 .product_id = 0xc101,
63         },
64         {
65                 .name       = "Philips/Sagemcom PicoPix 1020",
66                 .vendor_id  = 0x21e7,
67                 .product_id = 0x000e,
68         },
69 };
70
71 /* The header size on the wire is known to be always 24 bytes, regardless of
72  * the memory configuration enforced by different architechtures or compilers
73  * for struct am7xxx_header
74  */
75 #define AM7XXX_HEADER_WIRE_SIZE 24
76
77 struct _am7xxx_device {
78         libusb_device_handle *usb_device;
79         uint8_t buffer[AM7XXX_HEADER_WIRE_SIZE];
80         am7xxx_context *ctx;
81         am7xxx_device *next;
82 };
83
84 struct _am7xxx_context {
85         libusb_context *usb_context;
86         int log_level;
87         am7xxx_device *devices_list;
88 };
89
90 typedef enum {
91         AM7XXX_PACKET_TYPE_DEVINFO = 0x01,
92         AM7XXX_PACKET_TYPE_IMAGE   = 0x02,
93         AM7XXX_PACKET_TYPE_POWER   = 0x04,
94         AM7XXX_PACKET_TYPE_UNKNOWN = 0x05,
95 } am7xxx_packet_type;
96
97 struct am7xxx_generic_header {
98         uint32_t field0;
99         uint32_t field1;
100         uint32_t field2;
101         uint32_t field3;
102 };
103
104 struct am7xxx_devinfo_header {
105         uint32_t native_width;
106         uint32_t native_height;
107         uint32_t unknown0;
108         uint32_t unknown1;
109 };
110
111 struct am7xxx_image_header {
112         uint32_t format;
113         uint32_t width;
114         uint32_t height;
115         uint32_t image_size;
116 };
117
118 struct am7xxx_power_header {
119         uint32_t bit2;
120         uint32_t bit1;
121         uint32_t bit0;
122 };
123
124 /*
125  * Examples of packet headers:
126  *
127  * Image header:
128  * 02 00 00 00 00 10 3e 10 01 00 00 00 20 03 00 00 e0 01 00 00 53 E8 00 00
129  *
130  * Power header:
131  * 04 00 00 00 00 0c ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
132  */
133
134 struct am7xxx_header {
135         uint32_t packet_type;
136         uint8_t unknown0;
137         uint8_t header_data_len;
138         uint8_t unknown2;
139         uint8_t unknown3;
140         union {
141                 struct am7xxx_generic_header data;
142                 struct am7xxx_devinfo_header devinfo;
143                 struct am7xxx_image_header image;
144                 struct am7xxx_power_header power;
145         } header_data;
146 };
147
148
149 #ifdef DEBUG
150 static void debug_dump_devinfo_header(am7xxx_context *ctx, struct am7xxx_devinfo_header *d)
151 {
152         if (ctx == NULL || d == NULL)
153                 return;
154
155         debug(ctx, "Info header:\n");
156         debug(ctx, "\tnative_width:  0x%08x (%u)\n", d->native_width, d->native_width);
157         debug(ctx, "\tnative_height: 0x%08x (%u)\n", d->native_height, d->native_height);
158         debug(ctx, "\tunknown0:      0x%08x (%u)\n", d->unknown0, d->unknown0);
159         debug(ctx, "\tunknown1:      0x%08x (%u)\n", d->unknown1, d->unknown1);
160 }
161
162 static void debug_dump_image_header(am7xxx_context *ctx, struct am7xxx_image_header *i)
163 {
164         if (ctx == NULL || i == NULL)
165                 return;
166
167         debug(ctx, "Image header:\n");
168         debug(ctx, "\tformat:     0x%08x (%u)\n", i->format, i->format);
169         debug(ctx, "\twidth:      0x%08x (%u)\n", i->width, i->width);
170         debug(ctx, "\theight:     0x%08x (%u)\n", i->height, i->height);
171         debug(ctx, "\timage size: 0x%08x (%u)\n", i->image_size, i->image_size);
172 }
173
174 static void debug_dump_power_header(am7xxx_context *ctx, struct am7xxx_power_header *p)
175 {
176         if (ctx == NULL || p == NULL)
177                 return;
178
179         debug(ctx, "Power header:\n");
180         debug(ctx, "\tbit2: 0x%08x (%u)\n", p->bit2, p->bit2);
181         debug(ctx, "\tbit1: 0x%08x (%u)\n", p->bit1, p->bit1);
182         debug(ctx, "\tbit0: 0x%08x (%u)\n", p->bit0, p->bit0);
183 }
184
185 static void debug_dump_header(am7xxx_context *ctx, struct am7xxx_header *h)
186 {
187         if (ctx == NULL || h == NULL)
188                 return;
189
190         debug(ctx, "BEGIN\n");
191         debug(ctx, "packet_type:     0x%08x (%u)\n", h->packet_type, h->packet_type);
192         debug(ctx, "unknown0:        0x%02hhx (%hhu)\n", h->unknown0, h->unknown0);
193         debug(ctx, "header_data_len: 0x%02hhx (%hhu)\n", h->header_data_len, h->header_data_len);
194         debug(ctx, "unknown2:        0x%02hhx (%hhu)\n", h->unknown2, h->unknown2);
195         debug(ctx, "unknown3:        0x%02hhx (%hhu)\n", h->unknown3, h->unknown3);
196
197         switch(h->packet_type) {
198         case AM7XXX_PACKET_TYPE_DEVINFO:
199                 debug_dump_devinfo_header(ctx, &(h->header_data.devinfo));
200                 break;
201
202         case AM7XXX_PACKET_TYPE_IMAGE:
203                 debug_dump_image_header(ctx, &(h->header_data.image));
204                 break;
205
206         case AM7XXX_PACKET_TYPE_POWER:
207                 debug_dump_power_header(ctx, &(h->header_data.power));
208                 break;
209
210         default:
211                 debug(ctx, "Packet type not supported!\n");
212                 break;
213         }
214         debug(ctx, "END\n\n");
215 }
216
217 static inline unsigned int in_80chars(unsigned int i)
218 {
219         /* The 3 below is the length of "xx " where xx is the hex string
220          * representation of a byte */
221         return ((i+1) % (80/3));
222 }
223
224 static void trace_dump_buffer(am7xxx_context *ctx, const char *message,
225                               uint8_t *buffer, unsigned int len)
226 {
227         unsigned int i;
228
229         if (ctx == NULL || buffer == NULL || len == 0)
230                 return;
231
232         trace(ctx, "\n");
233         if (message)
234                 trace(ctx, "%s\n", message);
235
236         for (i = 0; i < len; i++) {
237                 trace(ctx, "%02hhX%c", buffer[i], (in_80chars(i) && (i < len - 1)) ? ' ' : '\n');
238         }
239         trace(ctx, "\n");
240 }
241 #else
242 static void debug_dump_header(am7xxx_context *ctx, struct am7xxx_header *h)
243 {
244         (void)ctx;
245         (void)h;
246 }
247
248 static void trace_dump_buffer(am7xxx_context *ctx, const char *message,
249                               uint8_t *buffer, unsigned int len)
250 {
251         (void)ctx;
252         (void)message;
253         (void)buffer;
254         (void)len;
255 }
256 #endif /* DEBUG */
257
258 static int read_data(am7xxx_device *dev, uint8_t *buffer, unsigned int len)
259 {
260         int ret;
261         int transferred = 0;
262
263         ret = libusb_bulk_transfer(dev->usb_device, 0x81, buffer, len, &transferred, 0);
264         if (ret != 0 || (unsigned int)transferred != len) {
265                 error(dev->ctx, "ret: %d\ttransferred: %d (expected %u)\n",
266                       ret, transferred, len);
267                 return ret;
268         }
269
270         trace_dump_buffer(dev->ctx, "<-- received", buffer, len);
271
272         return 0;
273 }
274
275 static int send_data(am7xxx_device *dev, uint8_t *buffer, unsigned int len)
276 {
277         int ret;
278         int transferred = 0;
279
280         trace_dump_buffer(dev->ctx, "sending -->", buffer, len);
281
282         ret = libusb_bulk_transfer(dev->usb_device, 1, buffer, len, &transferred, 0);
283         if (ret != 0 || (unsigned int)transferred != len) {
284                 error(dev->ctx, "ret: %d\ttransferred: %d (expected %u)\n",
285                       ret, transferred, len);
286                 return ret;
287         }
288
289         return 0;
290 }
291
292 static void serialize_header(struct am7xxx_header *h, uint8_t *buffer)
293 {
294         uint8_t **buffer_iterator = &buffer;
295
296         put_le32(h->packet_type, buffer_iterator);
297         put_8(h->unknown0, buffer_iterator);
298         put_8(h->header_data_len, buffer_iterator);
299         put_8(h->unknown2, buffer_iterator);
300         put_8(h->unknown3, buffer_iterator);
301         put_le32(h->header_data.data.field0, buffer_iterator);
302         put_le32(h->header_data.data.field1, buffer_iterator);
303         put_le32(h->header_data.data.field2, buffer_iterator);
304         put_le32(h->header_data.data.field3, buffer_iterator);
305 }
306
307 static void unserialize_header(uint8_t *buffer, struct am7xxx_header *h)
308 {
309         uint8_t **buffer_iterator = &buffer;
310
311         h->packet_type = get_le32(buffer_iterator);
312         h->unknown0 = get_8(buffer_iterator);
313         h->header_data_len = get_8(buffer_iterator);
314         h->unknown2 = get_8(buffer_iterator);
315         h->unknown3 = get_8(buffer_iterator);
316         h->header_data.data.field0 = get_le32(buffer_iterator);
317         h->header_data.data.field1 = get_le32(buffer_iterator);
318         h->header_data.data.field2 = get_le32(buffer_iterator);
319         h->header_data.data.field3 = get_le32(buffer_iterator);
320 }
321
322 static int read_header(am7xxx_device *dev, struct am7xxx_header *h)
323 {
324         int ret;
325
326         ret = read_data(dev, dev->buffer, AM7XXX_HEADER_WIRE_SIZE);
327         if (ret < 0)
328                 goto out;
329
330         unserialize_header(dev->buffer, h);
331
332         debug_dump_header(dev->ctx, h);
333
334         ret = 0;
335
336 out:
337         return ret;
338 }
339
340 static int send_header(am7xxx_device *dev, struct am7xxx_header *h)
341 {
342         int ret;
343
344         debug_dump_header(dev->ctx, h);
345
346         serialize_header(h, dev->buffer);
347         ret = send_data(dev, dev->buffer, AM7XXX_HEADER_WIRE_SIZE);
348         if (ret < 0)
349                 error(dev->ctx, "failed to send data\n");
350
351         return ret;
352 }
353
354 /* When level == AM7XXX_LOG_FATAL do not check the log_level from the context
355  * and print the message unconditionally, this makes it possible to print
356  * fatal messages even early on initialization, before the context has been
357  * set up */
358 static void log_message(am7xxx_context *ctx,
359                         int level,
360                         const char *function,
361                         int line,
362                         const char *fmt,
363                         ...)
364 {
365         va_list ap;
366
367         if (level == AM7XXX_LOG_FATAL || (ctx && level <= ctx->log_level)) {
368                 if (function) {
369                         fprintf(stderr, "%s", function);
370                         if (line)
371                                 fprintf(stderr, "[%d]", line);
372                         fprintf(stderr, ": ");
373                 }
374
375                 va_start(ap, fmt);
376                 vfprintf(stderr, fmt, ap);
377                 va_end(ap);
378         }
379
380         return;
381 }
382
383 static am7xxx_device *add_new_device(am7xxx_context *ctx)
384 {
385         am7xxx_device **devices_list;
386         am7xxx_device *new_device;
387
388         if (ctx == NULL) {
389                 fatal("context must not be NULL!\n");
390                 return NULL;
391         }
392
393         devices_list = &(ctx->devices_list);
394
395         new_device = malloc(sizeof(*new_device));
396         if (new_device == NULL) {
397                 fatal("cannot allocate a new device (%s)\n", strerror(errno));
398                 return NULL;
399         }
400         memset(new_device, 0, sizeof(*new_device));
401
402         new_device->ctx = ctx;
403
404         if (*devices_list == NULL) {
405                 *devices_list = new_device;
406         } else {
407                 am7xxx_device *prev = *devices_list;
408                 while (prev->next)
409                         prev = prev->next;
410                 prev->next = new_device;
411         }
412         return new_device;
413 }
414
415 static am7xxx_device *find_device(am7xxx_context *ctx,
416                                   unsigned int device_index)
417 {
418         unsigned int i = 0;
419         am7xxx_device *current;
420
421         if (ctx == NULL) {
422                 fatal("context must not be NULL!\n");
423                 return NULL;
424         }
425
426         current = ctx->devices_list;
427         while (current && i++ < device_index)
428                 current = current->next;
429
430         return current;
431 }
432
433 typedef enum {
434         SCAN_OP_BUILD_DEVLIST,
435         SCAN_OP_OPEN_DEVICE,
436 } scan_op;
437
438 /**
439  * This is where the central logic of multi-device support is.
440  *
441  * When 'op' == SCAN_OP_BUILD_DEVLIST the parameters 'open_device_index' and
442  * 'dev' are ignored; the function returns 0 on success and a negative value
443  * on error.
444  *
445  * When 'op' == SCAN_OP_OPEN_DEVICE the function opens the supported USB
446  * device with index 'open_device_index' and returns the correspondent
447  * am7xxx_device in the 'dev' parameter; the function returns 0 on success,
448  * 1 if the device was already open and a negative value on error.
449  *
450  * NOTES:
451  * if scan_devices() fails when called with 'op' == SCAN_OP_BUILD_DEVLIST,
452  * the caller might want to call am7xxx_shutdown() in order to remove
453  * devices possibly added before the failure.
454  */
455 static int scan_devices(am7xxx_context *ctx, scan_op op,
456                         unsigned int open_device_index, am7xxx_device **dev)
457 {
458         int num_devices;
459         libusb_device** list;
460         unsigned int current_index;
461         int i;
462         int ret;
463
464         if (ctx == NULL) {
465                 fatal("context must not be NULL!\n");
466                 return -EINVAL;
467         }
468         if (op == SCAN_OP_BUILD_DEVLIST && ctx->devices_list != NULL) {
469                 error(ctx, "device scan done already? Abort!\n");
470                 return -EINVAL;
471         }
472
473         num_devices = libusb_get_device_list(ctx->usb_context, &list);
474         if (num_devices < 0) {
475                 ret = -ENODEV;
476                 goto out;
477         }
478
479         current_index = 0;
480         for (i = 0; i < num_devices; i++) {
481                 struct libusb_device_descriptor desc;
482                 unsigned int j;
483
484                 ret = libusb_get_device_descriptor(list[i], &desc);
485                 if (ret < 0)
486                         continue;
487
488                 for (j = 0; j < ARRAY_SIZE(supported_devices); j++) {
489                         if (desc.idVendor == supported_devices[j].vendor_id
490                             && desc.idProduct == supported_devices[j].product_id) {
491
492                                 if (op == SCAN_OP_BUILD_DEVLIST) {
493                                         am7xxx_device *new_device;
494                                         info(ctx, "am7xxx device found, index: %d, name: %s\n",
495                                              current_index,
496                                              supported_devices[j].name);
497                                         new_device = add_new_device(ctx);
498                                         if (new_device == NULL) {
499                                                 /* XXX, the caller may want
500                                                  * to call am7xxx_shutdown() if
501                                                  * we fail here, as we may have
502                                                  * added some devices already
503                                                  */
504                                                 debug(ctx, "Cannot create a new device\n");
505                                                 ret = -ENODEV;
506                                                 goto out;
507                                         }
508                                 } else if (op == SCAN_OP_OPEN_DEVICE &&
509                                            current_index == open_device_index) {
510
511                                         *dev = find_device(ctx, open_device_index);
512                                         if (*dev == NULL) {
513                                                 ret = -ENODEV;
514                                                 goto out;
515                                         }
516
517                                         /* the usb device has already been opened */
518                                         if ((*dev)->usb_device) {
519                                                 debug(ctx, "(*dev)->usb_device already set\n");
520                                                 ret = 1;
521                                                 goto out;
522                                         }
523
524                                         ret = libusb_open(list[i], &((*dev)->usb_device));
525                                         if (ret < 0) {
526                                                 debug(ctx, "libusb_open failed\n");
527                                                 goto out;
528                                         }
529
530                                         libusb_set_configuration((*dev)->usb_device, 1);
531                                         libusb_claim_interface((*dev)->usb_device, 0);
532                                         goto out;
533                                 }
534                                 current_index++;
535                         }
536                 }
537         }
538
539         /* if we made it up to here we didn't find any device to open */
540         if (op == SCAN_OP_OPEN_DEVICE) {
541                 error(ctx, "Cannot find any device to open\n");
542                 ret = -ENODEV;
543                 goto out;
544         }
545
546         /* everything went fine when building the device list */
547         ret = 0;
548 out:
549         libusb_free_device_list(list, 1);
550         return ret;
551 }
552
553 int am7xxx_init(am7xxx_context **ctx)
554 {
555         int ret = 0;
556
557         *ctx = malloc(sizeof(**ctx));
558         if (*ctx == NULL) {
559                 fatal("cannot allocate the context (%s)\n", strerror(errno));
560                 ret = -ENOMEM;
561                 goto out;
562         }
563         memset(*ctx, 0, sizeof(**ctx));
564
565         /* Set the highest log level during initialization */
566         (*ctx)->log_level = AM7XXX_LOG_TRACE;
567
568         ret = libusb_init(&((*ctx)->usb_context));
569         if (ret < 0)
570                 goto out_free_context;
571
572         libusb_set_debug((*ctx)->usb_context, 3);
573
574         ret = scan_devices(*ctx, SCAN_OP_BUILD_DEVLIST , 0, NULL);
575         if (ret < 0) {
576                 error(*ctx, "scan_devices() failed\n");
577                 am7xxx_shutdown(*ctx);
578                 goto out;
579         }
580
581         /* Set a quieter log level as default for normal operation */
582         (*ctx)->log_level = AM7XXX_LOG_ERROR;
583         return 0;
584
585 out_free_context:
586         free(*ctx);
587         *ctx = NULL;
588 out:
589         return ret;
590 }
591
592 void am7xxx_shutdown(am7xxx_context *ctx)
593 {
594         am7xxx_device *current;
595
596         if (ctx == NULL) {
597                 fatal("context must not be NULL!\n");
598                 return;
599         }
600
601         current = ctx->devices_list;
602         while (current) {
603                 am7xxx_device *next = current->next;
604                 am7xxx_close_device(current);
605                 free(current);
606                 current = next;
607         }
608
609         libusb_exit(ctx->usb_context);
610         free(ctx);
611         ctx = NULL;
612 }
613
614 void am7xxx_set_log_level(am7xxx_context *ctx, am7xxx_log_level log_level)
615 {
616         ctx->log_level = log_level;
617 }
618
619 int am7xxx_open_device(am7xxx_context *ctx, am7xxx_device **dev,
620                        unsigned int device_index)
621 {
622         int ret;
623
624         if (ctx == NULL) {
625                 fatal("context must not be NULL!\n");
626                 return -EINVAL;
627         }
628
629         ret = scan_devices(ctx, SCAN_OP_OPEN_DEVICE, device_index, dev);
630         if (ret < 0) {
631                 errno = ENODEV;
632         } else if (ret > 0) {
633                 warning(ctx, "device %d already open\n", device_index);
634                 errno = EBUSY;
635                 ret = -EBUSY;
636         }
637
638         return ret;
639 }
640
641 int am7xxx_close_device(am7xxx_device *dev)
642 {
643         if (dev == NULL) {
644                 fatal("dev must not be NULL!\n");
645                 return -EINVAL;
646         }
647         if (dev->usb_device) {
648                 libusb_release_interface(dev->usb_device, 0);
649                 libusb_close(dev->usb_device);
650                 dev->usb_device = NULL;
651         }
652         return 0;
653 }
654
655 int am7xxx_get_device_info(am7xxx_device *dev,
656                            am7xxx_device_info *device_info)
657 {
658         int ret;
659         struct am7xxx_header h = {
660                 .packet_type     = AM7XXX_PACKET_TYPE_DEVINFO,
661                 .unknown0        = 0x00,
662                 .header_data_len = 0x00,
663                 .unknown2        = 0x3e,
664                 .unknown3        = 0x10,
665                 .header_data = {
666                         .devinfo = {
667                                 .native_width  = 0,
668                                 .native_height = 0,
669                                 .unknown0      = 0,
670                                 .unknown1      = 0,
671                         },
672                 },
673         };
674
675         ret = send_header(dev, &h);
676         if (ret < 0)
677                 return ret;
678
679         ret = read_header(dev, &h);
680         if (ret < 0)
681                 return ret;
682
683         device_info->native_width = h.header_data.devinfo.native_width;
684         device_info->native_height = h.header_data.devinfo.native_height;
685 #if 0
686         /* No reason to expose these in the public API until we know what they mean */
687         device_info->unknown0 = h.header_data.devinfo.unknown0;
688         device_info->unknown1 = h.header_data.devinfo.unknown1;
689 #endif
690
691         return 0;
692 }
693
694 int am7xxx_send_image(am7xxx_device *dev,
695                       am7xxx_image_format format,
696                       unsigned int width,
697                       unsigned int height,
698                       uint8_t *image,
699                       unsigned int image_size)
700 {
701         int ret;
702         struct am7xxx_header h = {
703                 .packet_type     = AM7XXX_PACKET_TYPE_IMAGE,
704                 .unknown0        = 0x00,
705                 .header_data_len = sizeof(struct am7xxx_image_header),
706                 .unknown2        = 0x3e,
707                 .unknown3        = 0x10,
708                 .header_data = {
709                         .image = {
710                                 .format     = format,
711                                 .width      = width,
712                                 .height     = height,
713                                 .image_size = image_size,
714                         },
715                 },
716         };
717
718         ret = send_header(dev, &h);
719         if (ret < 0)
720                 return ret;
721
722         if (image == NULL || image_size == 0) {
723                 warning(dev->ctx, "Not sending any data, check the 'image' or 'image_size' parameters\n");
724                 return 0;
725         }
726
727         return send_data(dev, image, image_size);
728 }
729
730 int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mode)
731 {
732         int ret;
733         struct am7xxx_header h = {
734                 .packet_type     = AM7XXX_PACKET_TYPE_POWER,
735                 .unknown0        = 0x00,
736                 .header_data_len = sizeof(struct am7xxx_power_header),
737                 .unknown2        = 0x3e,
738                 .unknown3        = 0x10,
739         };
740
741         switch(mode) {
742         case AM7XXX_POWER_OFF:
743                 h.header_data.power.bit2 = 0;
744                 h.header_data.power.bit1 = 0;
745                 h.header_data.power.bit0 = 0;
746                 break;
747
748         case AM7XXX_POWER_LOW:
749                 h.header_data.power.bit2 = 0;
750                 h.header_data.power.bit1 = 0;
751                 h.header_data.power.bit0 = 1;
752
753         case AM7XXX_POWER_MIDDLE:
754                 h.header_data.power.bit2 = 0;
755                 h.header_data.power.bit1 = 1;
756                 h.header_data.power.bit0 = 0;
757                 break;
758
759         case AM7XXX_POWER_HIGH:
760                 h.header_data.power.bit2 = 0;
761                 h.header_data.power.bit1 = 1;
762                 h.header_data.power.bit0 = 1;
763                 break;
764
765         case AM7XXX_POWER_TURBO:
766                 h.header_data.power.bit2 = 1;
767                 h.header_data.power.bit1 = 0;
768                 h.header_data.power.bit0 = 0;
769                 break;
770
771         default:
772                 error(dev->ctx, "Power mode not supported!\n");
773                 return -EINVAL;
774         };
775
776         ret = send_header(dev, &h);
777         if (ret < 0)
778                 return ret;
779
780         return 0;
781 }