libmtp.c

来自「Media transfer protocol implementation o」· C语言 代码 · 共 2,016 行 · 第 1/5 页

C
2,016
字号
 * @param attribute_id PTP attribute ID * @param value_default Default value to return on failure * @return a value */static uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,				  uint16_t const attribute_id, uint8_t const value_default){  PTPPropertyValue propval;  uint8_t retval = value_default;  PTPParams *params = (PTPParams *) device->params;  uint16_t ret;  if ( device == NULL ) {    return value_default;  }  ret = ptp_mtp_getobjectpropvalue(params, object_id,                                   attribute_id,                                   &propval,                                   PTP_DTC_UINT8);  if (ret == PTP_RC_OK) {    retval = propval.u8;  }  return retval;}/** * Sets an object attribute from a string * * @param device a pointer to an MTP device. * @param object_id Object reference * @param attribute_id PTP attribute ID * @param string string value to set * @return 0 on success, any other value means failure */static int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_id,			     uint16_t const attribute_id, char const * const string){  PTPPropertyValue propval;  PTPParams *params = (PTPParams *) device->params;  uint16_t ret;  if (device == NULL || string == NULL) {    return -1;  }  propval.str = (char *) string;  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_STR);  if (ret != PTP_RC_OK) {    printf("set_object_string(): could not set object string.\n");    printf("Return code: 0x%04x (look this up in ptp.h for an explanation).\n",  ret);    return -1;  }  return 0;}/** * Sets an object attribute from an unsigned 32-bit integer * * @param device a pointer to an MTP device. * @param object_id Object reference * @param attribute_id PTP attribute ID * @param value 32-bit unsigned integer to set * @return 0 on success, any other value means failure */static int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,			  uint16_t const attribute_id, uint32_t const value){  PTPPropertyValue propval;  PTPParams *params = (PTPParams *) device->params;  uint16_t ret;  if (device == NULL) {    return -1;  }  propval.u32 = value;  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT32);  if (ret != PTP_RC_OK) {    printf("set_object_u32(): could not set unsigned 32bit integer property.\n");    printf("Return code: 0x%04x (look this up in ptp.h for an explanation).\n",  ret);    return -1;  }  return 0;}/** * Sets an object attribute from an unsigned 16-bit integer * * @param device a pointer to an MTP device. * @param object_id Object reference * @param attribute_id PTP attribute ID * @param value 16-bit unsigned integer to set * @return 0 on success, any other value means failure */static int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,			  uint16_t const attribute_id, uint16_t const value){  PTPPropertyValue propval;  PTPParams *params = (PTPParams *) device->params;  uint16_t ret;  if (device == NULL) {    return 1;  }  propval.u16 = value;  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT16);  if (ret != PTP_RC_OK) {    printf("set_object_u16(): could not set unsigned 16bit integer property.\n");    printf("Return code: 0x%04x (look this up in ptp.h for an explanation).\n",  ret);    return 1;  }  return 0;}/** * Sets an object attribute from an unsigned 8-bit integer * * @param device a pointer to an MTP device. * @param object_id Object reference * @param attribute_id PTP attribute ID * @param value 8-bit unsigned integer to set * @return 0 on success, any other value means failure */static int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,			 uint16_t const attribute_id, uint8_t const value){  PTPPropertyValue propval;  PTPParams *params = (PTPParams *) device->params;  uint16_t ret;  if (device == NULL) {    return 1;  }  propval.u8 = value;  ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT8);  if (ret != PTP_RC_OK) {    printf("set_object_u8(): could not set unsigned 8bit integer property.\n");    printf("Return code: 0x%04x (look this up in ptp.h for an explanation).\n",  ret);    return 1;  }  return 0;}/** * Get a list of the supported devices. * * The developers depend on users of this library to constantly * add in to the list of supported devices. What we need is the * device name, USB Vendor ID (VID) and USB Product ID (PID). * put this into a bug ticket at the project homepage, please. * The VID/PID is used to let e.g. udev lift the device to * console userspace access when it's plugged in. * * @param devices a pointer to a pointer that will hold a device *        list after the call to this function, if it was *        successful. * @param numdevs a pointer to an integer that will hold the number *        of devices in the device list if the call was successful. * @return 0 if the list was successfull retrieved, any other *        value means failure. */int LIBMTP_Get_Supported_Devices_List(LIBMTP_device_entry_t ** const devices, int * const numdevs){  // Just dispatch to libusb glue file...  return get_device_list(devices, numdevs);}/** * Get the first connected MTP device. There is currently no API for * retrieveing multiple devices. * @return a device pointer. */LIBMTP_mtpdevice_t *LIBMTP_Get_First_Device(void){  uint8_t interface_number;  PTPParams *params;  PTP_USB *ptp_usb;  PTPStorageIDs storageIDs;  uint32_t storageID = 0;  PTPDevicePropDesc dpd;  uint8_t batteryLevelMax = 100; // Some default  uint16_t ret;  uint32_t i;  LIBMTP_mtpdevice_t *tmpdevice;	uint8_t remaining_directories;  // Allocate a parameter block  params = (PTPParams *) malloc(sizeof(PTPParams));  params->cd_locale_to_ucs2 = iconv_open(UCS_2_INTERNAL, "UTF-8");  params->cd_ucs2_to_locale = iconv_open("UTF-8", UCS_2_INTERNAL);  if (params->cd_locale_to_ucs2 == (iconv_t) -1 || params->cd_ucs2_to_locale == (iconv_t) -1) {    printf("LIBMTP panic: could not open iconv() converters to/from UCS-2!\n");    return NULL;  }  ptp_usb = (PTP_USB *) malloc(sizeof(PTP_USB));  // Callbacks and stuff  ptp_usb->callback_active = 0;  ptp_usb->current_transfer_total = 0;  ptp_usb->current_transfer_complete = 0;  ptp_usb->current_transfer_callback = NULL;  // get storage ID  ret = connect_first_device(params, ptp_usb, &interface_number);  switch (ret)    {    case PTP_CD_RC_CONNECTED:      printf("Connected to MTP device.\n");      break;    case PTP_CD_RC_NO_DEVICES:      printf("No MTP devices.\n");      return NULL;    case PTP_CD_RC_ERROR_CONNECTING:      printf("Connection error.\n");      return NULL;    }  // get storage ID  if (ptp_getstorageids (params, &storageIDs) == PTP_RC_OK) {    if (storageIDs.n > 0)      storageID = storageIDs.Storage[0];    free(storageIDs.Storage);  }  // Make sure there are no handlers  params->handles.Handler = NULL;  // Just cache the device information for any later use.  if (ptp_getdeviceinfo(params, &params->deviceinfo) != PTP_RC_OK) {    goto error_handler;  }  // Get battery maximum level  if (ptp_property_issupported(params, PTP_DPC_BatteryLevel)) {    if (ptp_getdevicepropdesc(params, PTP_DPC_BatteryLevel, &dpd) != PTP_RC_OK) {      printf("LIBMTP_Get_First_Device(): Unable to retrieve battery max level.\n");      goto error_handler;    }    // if is NULL, just leave as default    if (dpd.FORM.Range.MaximumValue.u8 != 0) {      batteryLevelMax = dpd.FORM.Range.MaximumValue.u8;    }    ptp_free_devicepropdesc(&dpd);  }  // OK everything got this far, so it is time to create a device struct!  tmpdevice = (LIBMTP_mtpdevice_t *) malloc(sizeof(LIBMTP_mtpdevice_t));  tmpdevice->interface_number = interface_number;  tmpdevice->params = (void *) params;  tmpdevice->usbinfo = (void *) ptp_usb;  tmpdevice->storage_id = storageID;  tmpdevice->maximum_battery_level = batteryLevelMax;  // Set all default folders to 0 == root directory  tmpdevice->default_music_folder = 0;  tmpdevice->default_playlist_folder = 0;  tmpdevice->default_picture_folder = 0;  tmpdevice->default_video_folder = 0;  tmpdevice->default_organizer_folder = 0;  tmpdevice->default_zencast_folder = 0;  tmpdevice->default_album_folder = 0;  /*   * Then get the handles and try to locate the default folders.   * This has the desired side effect of cacheing all handles from   * the device which speeds up later operations.   */  flush_handles(tmpdevice);  /*   * Remaining directories to get the handles to.   * We can stop when done this to save time   */  remaining_directories = 7;  for (i = 0; i < params->handles.n && remaining_directories > 0; i++) {    PTPObjectInfo oi;    if (ptp_getobjectinfo(params, params->handles.Handler[i], &oi) == PTP_RC_OK) {      // Ignore non-folders      if ( oi.ObjectFormat != PTP_OFC_Association )	continue;      if ( oi.Filename == NULL)	continue;      if (!strcmp(oi.Filename, "Music")) {	tmpdevice->default_music_folder = params->handles.Handler[i];	remaining_directories--;	continue;      } else if ((!strcmp(oi.Filename, "My Playlists")) ||       			 (!strcmp(oi.Filename, "Playlists"))) {	tmpdevice->default_playlist_folder = params->handles.Handler[i];	remaining_directories--;	continue;      } else if (!strcmp(oi.Filename, "Pictures")) {	tmpdevice->default_picture_folder = params->handles.Handler[i];	remaining_directories--;	continue;      } else if (!strcmp(oi.Filename, "Video")) {	tmpdevice->default_video_folder = params->handles.Handler[i];	remaining_directories--;	continue;      } else if (!strcmp(oi.Filename, "My Organizer")) {	tmpdevice->default_organizer_folder = params->handles.Handler[i];	remaining_directories--;	continue;      } else if (!strcmp(oi.Filename, "ZENcast")) {	tmpdevice->default_zencast_folder = params->handles.Handler[i];	remaining_directories--;	continue;      } else if (!strcmp(oi.Filename, "Albums")) {	tmpdevice->default_album_folder = params->handles.Handler[i];	remaining_directories--;	continue;      }    } else {      printf("LIBMTP panic: Found a bad handle, trying to ignore it.\n");    }  }  return tmpdevice;  // Then close it again. error_handler:  close_device(ptp_usb, params, interface_number);  // TODO: libgphoto2 does not seem to be able to free the deviceinfo  // ptp_free_deviceinfo(&params->deviceinfo);  if (params->handles.Handler != NULL) {    free(params->handles.Handler);  }  return NULL;}/** * This closes and releases an allocated MTP device. * @param device a pointer to the MTP device to release. */void LIBMTP_Release_Device(LIBMTP_mtpdevice_t *device){  PTPParams *params = (PTPParams *) device->params;  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;  close_device(ptp_usb, params, device->interface_number);  // Free the device info and any handler  // TODO: libgphoto2 does not seem to be able to free the deviceinfo  // ptp_free_deviceinfo(&params->deviceinfo);  if (params->handles.Handler != NULL) {    free(params->handles.Handler);    params->handles.Handler = NULL;  }  // Free iconv() converters...  iconv_close(params->cd_locale_to_ucs2);  iconv_close(params->cd_ucs2_to_locale);  free(device);}/** * This function refresh the internal handle list whenever * the items stored inside the device is altered. On operations * that do not add or remove objects, this is typically not * called. * @param device a pointer to the MTP device to flush handles for. */static void flush_handles(LIBMTP_mtpdevice_t *device){  PTPParams *params = (PTPParams *) device->params;  uint16_t ret;  if (params->handles.Handler != NULL) {    free(params->handles.Handler);  }  // Get all the handles if we haven't already done that  ret = ptp_getobjecthandles(params,			     PTP_GOH_ALL_STORAGE,			     PTP_GOH_ALL_FORMATS,			     PTP_GOH_ALL_ASSOCS,			     &params->handles);  if (ret != PTP_RC_OK) {    printf("flush_handles(): LIBMTP panic: Could not get object handles...\n");    printf("Return code: 0x%04x (look this up in ptp.h for an explanation).\n",  ret);  }  return;}/** * This function dumps out a large chunk of textual information * provided from the PTP protocol and additionally some extra * MTP-specific information where applicable. * @param device a pointer to the MTP device to report info from. */void LIBMTP_Dump_Device_Info(LIBMTP_mtpdevice_t *device){  int i;  PTPParams *params = (PTPParams *) device->params;  PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;  printf("USB low-level info:\n");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?