X-Git-Url: https://git.ao2.it/libam7xxx.git/blobdiff_plain/90247e36e90bebe6c8b80393d2a037b054808597..6d2d8613958e1f0ef011e9d848426086caafe9db:/src/am7xxx.c?ds=sidebyside diff --git a/src/am7xxx.c b/src/am7xxx.c index 5481075..83d9a91 100644 --- a/src/am7xxx.c +++ b/src/am7xxx.c @@ -91,6 +91,11 @@ static struct am7xxx_usb_device_descriptor supported_devices[] = { .vendor_id = 0x21e7, .product_id = 0x000e, }, + { + .name = "Philips/Sagemcom PicoPix 2055", + .vendor_id = 0x21e7, + .product_id = 0x0016, + }, }; /* The header size on the wire is known to be always 24 bytes, regardless of @@ -102,6 +107,7 @@ static struct am7xxx_usb_device_descriptor supported_devices[] = { struct _am7xxx_device { libusb_device_handle *usb_device; uint8_t buffer[AM7XXX_HEADER_WIRE_SIZE]; + am7xxx_device_info *device_info; am7xxx_context *ctx; am7xxx_device *next; }; @@ -234,7 +240,10 @@ static void debug_dump_header(am7xxx_context *ctx, struct am7xxx_header *h) debug(ctx, "BEGIN\n"); debug(ctx, "packet_type: 0x%08x (%u)\n", h->packet_type, h->packet_type); - debug(ctx, "direction: 0x%02hhx (%hhu)\n", h->direction, h->direction); + debug(ctx, "direction: 0x%02hhx (%hhu) (%s)\n", h->direction, h->direction, + h->direction == AM7XXX_DIRECTION_IN ? "IN" : + h->direction == AM7XXX_DIRECTION_OUT ? "OUT" : + "UNKNOWN"); debug(ctx, "header_data_len: 0x%02hhx (%hhu)\n", h->header_data_len, h->header_data_len); debug(ctx, "unknown2: 0x%02hhx (%hhu)\n", h->unknown2, h->unknown2); debug(ctx, "unknown3: 0x%02hhx (%hhu)\n", h->unknown3, h->unknown3); @@ -378,16 +387,17 @@ static int read_header(am7xxx_device *dev, struct am7xxx_header *h) unserialize_header(dev->buffer, h); - debug_dump_header(dev->ctx, h); - if (h->direction == AM7XXX_DIRECTION_IN) { ret = 0; } else { error(dev->ctx, - "Received a packet with direction AM7XXX_DIRECTION_OUT, weird!\n"); + "Expected an AM7XXX_DIRECTION_IN packet, got one with direction = %d. Weird!\n", + h->direction); ret = -EINVAL; } + debug_dump_header(dev->ctx, h); + out: return ret; } @@ -398,7 +408,13 @@ static int send_header(am7xxx_device *dev, struct am7xxx_header *h) debug_dump_header(dev->ctx, h); + /* For symmetry with read_header() we should check here for + * h->direction == AM7XXX_DIRECTION_OUT but we just ensure that in all + * the callers and save some cycles here. + */ + serialize_header(h, dev->buffer); + ret = send_data(dev, dev->buffer, AM7XXX_HEADER_WIRE_SIZE); if (ret < 0) error(dev->ctx, "failed to send data\n"); @@ -445,8 +461,6 @@ static am7xxx_device *add_new_device(am7xxx_context *ctx) return NULL; } - devices_list = &(ctx->devices_list); - new_device = malloc(sizeof(*new_device)); if (new_device == NULL) { fatal("cannot allocate a new device (%s)\n", strerror(errno)); @@ -456,6 +470,8 @@ static am7xxx_device *add_new_device(am7xxx_context *ctx) new_device->ctx = ctx; + devices_list = &(ctx->devices_list); + if (*devices_list == NULL) { *devices_list = new_device; } else { @@ -541,8 +557,8 @@ static int scan_devices(am7xxx_context *ctx, scan_op op, continue; for (j = 0; j < ARRAY_SIZE(supported_devices); j++) { - if (desc.idVendor == supported_devices[j].vendor_id - && desc.idProduct == supported_devices[j].product_id) { + if (desc.idVendor == supported_devices[j].vendor_id && + desc.idProduct == supported_devices[j].product_id) { if (op == SCAN_OP_BUILD_DEVLIST) { am7xxx_device *new_device; @@ -659,6 +675,7 @@ AM7XXX_PUBLIC void am7xxx_shutdown(am7xxx_context *ctx) while (current) { am7xxx_device *next = current->next; am7xxx_close_device(current); + free(current->device_info); free(current); current = next; } @@ -686,12 +703,28 @@ AM7XXX_PUBLIC int am7xxx_open_device(am7xxx_context *ctx, am7xxx_device **dev, ret = scan_devices(ctx, SCAN_OP_OPEN_DEVICE, device_index, dev); if (ret < 0) { errno = ENODEV; + goto out; } else if (ret > 0) { warning(ctx, "device %d already open\n", device_index); errno = EBUSY; ret = -EBUSY; + goto out; } + /* Philips/Sagemcom PicoPix projectors require that the DEVINFO packet + * is the first one to be sent to the device in order for it to + * successfully return the correct device information. + * + * So, if there is not a cached version of it (from a previous open), + * we ask for device info at open time, + */ + if ((*dev)->device_info == NULL) { + ret = am7xxx_get_device_info(*dev, NULL); + if (ret < 0) + error(ctx, "cannot get device info\n"); + } + +out: return ret; } @@ -729,6 +762,11 @@ AM7XXX_PUBLIC int am7xxx_get_device_info(am7xxx_device *dev, }, }; + if (dev->device_info) { + memcpy(device_info, dev->device_info, sizeof(*device_info)); + return 0; + } + ret = send_header(dev, &h); if (ret < 0) return ret; @@ -737,12 +775,27 @@ AM7XXX_PUBLIC int am7xxx_get_device_info(am7xxx_device *dev, if (ret < 0) return ret; - device_info->native_width = h.header_data.devinfo.native_width; - device_info->native_height = h.header_data.devinfo.native_height; + if (h.packet_type != AM7XXX_PACKET_TYPE_DEVINFO) { + error(dev->ctx, "expected packet type: %d, got %d instead!\n", + AM7XXX_PACKET_TYPE_DEVINFO, h.packet_type); + errno = ENOTSUP; + return -ENOTSUP; + } + + dev->device_info = malloc(sizeof(*dev->device_info)); + if (dev->device_info == NULL) { + error(dev->ctx, "cannot allocate a device info (%s)\n", + strerror(errno)); + return -ENOMEM; + } + memset(dev->device_info, 0, sizeof(*dev->device_info)); + + dev->device_info->native_width = h.header_data.devinfo.native_width; + dev->device_info->native_height = h.header_data.devinfo.native_height; #if 0 /* No reason to expose these in the public API until we know what they mean */ - device_info->unknown0 = h.header_data.devinfo.unknown0; - device_info->unknown1 = h.header_data.devinfo.unknown1; + dev->device_info->unknown0 = h.header_data.devinfo.unknown0; + dev->device_info->unknown1 = h.header_data.devinfo.unknown1; #endif return 0; @@ -846,7 +899,7 @@ AM7XXX_PUBLIC int am7xxx_send_image(am7xxx_device *dev, return send_data(dev, image, image_size); } -AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mode) +AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power) { int ret; struct am7xxx_header h = { @@ -857,7 +910,7 @@ AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mo .unknown3 = 0x10, }; - switch(mode) { + switch(power) { case AM7XXX_POWER_OFF: h.header_data.power.bit2 = 0; h.header_data.power.bit1 = 0; @@ -889,7 +942,7 @@ AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mo break; default: - error(dev->ctx, "Power mode not supported!\n"); + error(dev->ctx, "Unsupported power mode.\n"); return -EINVAL; };