X-Git-Url: https://git.ao2.it/libam7xxx.git/blobdiff_plain/2c897cad505d3ba27723dcff7252ff123d90ab53..521c3915354a7119b67969fe9824b31710d732ca:/src/am7xxx.c diff --git a/src/am7xxx.c b/src/am7xxx.c index c039147..e809c55 100644 --- a/src/am7xxx.c +++ b/src/am7xxx.c @@ -107,7 +107,9 @@ 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; + const struct am7xxx_usb_device_descriptor *desc; am7xxx_device *next; }; @@ -390,7 +392,8 @@ static int read_header(am7xxx_device *dev, struct am7xxx_header *h) 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; } @@ -449,7 +452,8 @@ static void log_message(am7xxx_context *ctx, return; } -static am7xxx_device *add_new_device(am7xxx_context *ctx) +static am7xxx_device *add_new_device(am7xxx_context *ctx, + const struct am7xxx_usb_device_descriptor *desc) { am7xxx_device **devices_list; am7xxx_device *new_device; @@ -467,6 +471,7 @@ static am7xxx_device *add_new_device(am7xxx_context *ctx) memset(new_device, 0, sizeof(*new_device)); new_device->ctx = ctx; + new_device->desc = desc; devices_list = &(ctx->devices_list); @@ -555,15 +560,15 @@ 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; info(ctx, "am7xxx device found, index: %d, name: %s\n", current_index, supported_devices[j].name); - new_device = add_new_device(ctx); + new_device = add_new_device(ctx, &supported_devices[j]); if (new_device == NULL) { /* XXX, the caller may want * to call am7xxx_shutdown() if @@ -596,8 +601,28 @@ static int scan_devices(am7xxx_context *ctx, scan_op op, goto out; } - libusb_set_configuration((*dev)->usb_device, 2); - libusb_claim_interface((*dev)->usb_device, 0); + /* XXX, the device is now open, if any + * of the calls below fail we need to + * close it again before bailing out. + */ + + ret = libusb_set_configuration((*dev)->usb_device, 2); + if (ret < 0) { + debug(ctx, "libusb_set_configuration failed\n"); + debug(ctx, "Cannot set configuration 2\n"); + goto out_libusb_close; + } + + ret = libusb_claim_interface((*dev)->usb_device, 0); + if (ret < 0) { + debug(ctx, "libusb_claim_interface failed\n"); + debug(ctx, "Cannot claim interface 0\n"); +out_libusb_close: + libusb_close((*dev)->usb_device); + (*dev)->usb_device = NULL; + goto out; + } + goto out; } current_index++; @@ -673,6 +698,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; } @@ -700,12 +726,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; } @@ -743,6 +785,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; @@ -751,12 +798,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;