Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage on other platforms. #1

Open
Nailik opened this issue Jul 13, 2019 · 30 comments
Open

Usage on other platforms. #1

Nailik opened this issue Jul 13, 2019 · 30 comments

Comments

@Nailik
Copy link

Nailik commented Jul 13, 2019

Hi,
i really like the work you did here. I'm trying to use this on Android but my current Problem is, that i don't really now how IWiaItemExtras::Escape method works and what it exaclty sends. (My attemps so far had no affect on the camera).
I would be happy if you can help me out!

@pixeltris
Copy link
Owner

IWiaItemExtras and related interfaces belong to Microsoft's Windows Image Acquisition (WIA) API which is essentially an abstraction layer on top of PTP (as far as I'm aware). The reason why I chose to use that API is because Sony uses it for their Imaging Edge software on Windows and I could easily hook the functions to log the data sent to the camera. On Mac I think they seem to use libusb.

I'm not familiar with Android development, how are you communicating with the USB? Something like libusb? You could sniff the traffic of gphoto2 using Wireshark and see if there are any additional packets you need to send to the device which might be missing from the code in this repo due to being handled by the WIA API.

@Nailik
Copy link
Author

Nailik commented Jul 13, 2019

I use the default Usb implementation for Android (https://developer.android.com/guide/topics/connectivity/usb/host) where i can select the out endpoint (bulk and out).
I will check out if i can find a PTP related API for Android. Thank you so far.
Edit:
There is, but no real information https://developer.android.com/reference/android/mtp/package-summary

@Nailik Nailik closed this as completed Jul 13, 2019
@Nailik Nailik reopened this Jul 13, 2019
@pixeltris
Copy link
Owner

https://github.com/michaelzoech/remoteyourcam-usb this looks like a great starting point, it has handlers for Canon / Nikon cameras, the protocols should be the same for the Sony cameras.

https://github.com/michaelzoech/remoteyourcam-usb/blob/master/src/com/remoteyourcam/usb/ptp/PtpConstants.java here are the opcodes for the Canon / Nikon cameras. The opcodes around 0x1000 are common among all cameras using PTP so that would probably be a good place to start to ensure you're successfully communicating with the camera. Once you have something working you can then move onto the vendor specific opcodes which are used to control the functions of the camera https://github.com/pixeltris/SonyAlphaUSB/blob/master/SonyAlphaUSB/Ids.cs

@Nailik
Copy link
Author

Nailik commented Jul 13, 2019

I needed some time to build this and to dig into the code but it's working! Thank you very much, saved my month probably.

@Nailik
Copy link
Author

Nailik commented Jul 14, 2019

Connection works now, i've seen that you don't use the capture code aroung 0x1000 (so you don't use 0x100E), i tested this one - doesn't work. What you actually do is using 2 opcodes, one for the type of the settings, you name it MainSettings and one to start the capture - that's my new problem. The remoteyourcam code is easy to adjust to set the camera to pc mode but the capture doesn't work, also there is never a usage of 2 codes for one request and the bytearray i send to the camera to set it to pc mode is completely different from your code or the wireshark capture so i have no idea where to place the second opcode yet.

@pixeltris
Copy link
Owner

pixeltris commented Jul 14, 2019

Yea I don't think the sony alpha cameras respond to the regular type of image capture, instead there are operations for pressing/releasing the shutter (in the same way that you would take a picture manually).

This repo currently doesn't have a proper handlers for this (I will get around to doing this eventually). ghoto2 has an implementation PTP_DPC_SONY_AutoFocus / PTP_DPC_SONY_Capture are half/full press of the shutter button, the first requests is pressing the button down, it then waits for the camera to focus (based on auto focus settings), then it releases the shutter button. Then you need to get the image using the standard requests 0x1008 / 0x1009. So yea it's a little involved!

And yea sorry my naming conventions probably aren't correct for MainSetting and such. I'm not super familiar with PTP in general, I just implemented what I observed when logging the calls from the Sony Imaging Edge software.

@Nailik
Copy link
Author

Nailik commented Jul 14, 2019

What i know from the wireless implementation of the Sony APi is, that only A7iii and A9 etc need to have a half press (and only if there is no timer, so if you set the timer to 2 sec and mf then you don't need to call the half press first) and for (my) a6300 you don't need half press at all (i tried it with your code too).
To better explain what the difference between our code (how we connect) (and i have to send 0x1002 before 0x9201):
https://pastebin.com/4yJMrExA

@pixeltris
Copy link
Owner

If things don't seem to quite match up I'd suggest logging what the Imaging Edge software does with Wireshark and just copy that. It's likely that the WIA API does some additional stuff behind the scenes and possibly byte order changes which is why things might look a little different.

From what I can tell though gphoto2 uses the same image capture logic for a6300 as it does a7iii (you could always set up gphoto2 and confirm this).

@Nailik
Copy link
Author

Nailik commented Jul 14, 2019

I got it, it was not that the packet was wrong but WIA sends another packet after your shoot comand, that looks just a little bit different (without the 0xc2d2 part and with a 2 instead of a 1). I'm able to capture images with my phone! - But did you every notice that you're capture function triggers the capture but doesn't actually save the pic? (same as the sony remote windows application - but i think it's a weird behavior)

@pixeltris
Copy link
Owner

pixeltris commented Jul 14, 2019

Great! I think if it's in MF it will always take the picture, but AF it has to actually gain focus before it will take the picture. This is something I haven't handled properly yet but the gphoto2 implementation that I linked before handles it and should capture the image 100% of the time. Roughly copying what they do should fix that issue.

@Nailik
Copy link
Author

Nailik commented Jul 14, 2019

What i have red so far it's only possible to store the images on the camera on A7iii (and maybe A9), all other cameras only will send the image via usb when it's requested but not store it actually.
Read this here https://briansmith.com/sony-releases-imaging-edge-software/?fbclid=IwAR1UUvKVGnfFir6Riz4ofGx3u42wB3hr_KGphoUtB_i1naAf-UiE6vMbMUc

Depends on the camera. Only a7 III & a7R III can save to PC AND SD Card. All others will only save to PC when tethering. Doen’t matter if you use Capture One Pro or Imaging Edge that’s controlled by hardware not firmware.

@pixeltris
Copy link
Owner

Yea I noticed that, it's a little unfortunate. Maybe if something in PTP supports transferring images to the camera you could make a hacky workaround.

@Nailik
Copy link
Author

Nailik commented Jul 15, 2019

There must be another option because the Sony RM-SPR1 (https://www.sony.de/electronics/kameras-mit-wechselobjektiv-stative-fernbedienungen/rm-spr1) can trigger the capture and it will be saved onto the camera.

@pixeltris
Copy link
Owner

Interesting, I assume that's done on a different protocol or something? There seem to be a couple of third party products which do the same thing. Maybe someone has documented it somewhere? I assume you'd need some micro usb MITM device to sniff the packets if not.

@Nailik
Copy link
Author

Nailik commented Jul 15, 2019

Looks like there are some special sony pins according to https://www.dpreview.com/forums/thread/3551161
so it's not a thing you could do with a normal usb cable.

@cyrilpreiss
Copy link

Hi nailik, did you manage to control your sony camera on android ?

@Nailik
Copy link
Author

Nailik commented Jan 22, 2020

Yes i managed it, i can call the shutter - not more yet. I'm currently working on a flutter plugin for usb (which also works). At the moment i try to get it working on Windows too but i have problems with libusb.

@Nailik
Copy link
Author

Nailik commented Apr 13, 2020

Hey @pixeltris I'm still working on this and I wonder if you could help me.
When you captured the usb data of the imaging edge software, how did you translate it to what you send with wia.
I'm still not getting why the wireshark data only partl matches the request buffer.

@pixeltris
Copy link
Owner

pixeltris commented Apr 14, 2020

The official software uses WIA so I hooked the WIA function IWiaItemExtras::Escape as can be seen here and wrote my own crappy logging for that (so that I could log camera values and stuff).

I didn't try going down the wireshark route so I'm not sure how the data should look at a raw USB protocol level so I'm not much help there unfortunately!

@Nailik
Copy link
Author

Nailik commented Apr 14, 2020

Ahh I see, you wrote "I just implemented what I observed when logging calls from Sony imaging edge software" (Some comments above), how did you look the calls without wireshark?

@pixeltris
Copy link
Owner

pixeltris commented Apr 15, 2020

As I mentioned I hooked the WIA function IWiaItemExtras::Escape which is the function used by the official software to transfer data between the camera. It is therefore possible to log the data before it even hits driver / wireshark level, or even modify data if desired.

If you're not too sure what I mean by function hooking you can read this Wikipedia page which gives an overview of how it works https://en.wikipedia.org/wiki/Hooking

If you want to know exactly how the hooking works in this specific case: Program.cs will call WIALogger.Run() if the "wlog" command line argument is passed. That Run function will load the imaging edge executable in a suspended state, inject the dll SonyAlphaUSBLoader.dll which loads the .NET runtime and loads the C# code into the process, the C# code then hooks the IWiaItemExtras::Escape function (within the context of the imaging edge process) and then resumes the executable. See WIALogger.cs / SonyAlphaUSBLoader.cpp

You can use an API monitor (http://www.rohitab.com/apimonitor) if you want to log the IWiaItemExtras::Escape function without using my convoluted hooking mechanism, but you'd need to grab the xml definitions from here. I didn't find this way of monitoring too useful as it isn't easy to filter the data you actually want, and data is constantly communicated between the camera. That's why I wrote my own logger.

@Nailik
Copy link
Author

Nailik commented Apr 16, 2020

Thank you for your nice explanation! I missunderstood "hooking" and i see why you use your own mechanism, because the liveview can't be turned off.

@Nailik
Copy link
Author

Nailik commented May 31, 2020

Hi there, i'm still working on this and i found some issues and would like you to recheck it.
Problem on my A6300:
i get this in the settings bytes:

0b 50 //code for metering mode
04 00 //data type = 4
00 02 01 00  //gets skipped
02 00 //value = 2
02  //subdata value = 2
03 00 //num = 3
04 00 //1st option = 4
01 00 //2nd option = 1
02 80 //3rd option = 02 08 but should be 2 (as current value)

The thing is that metering mode gives me 02 80 as 3rd option for "center" but actually it should be 02 00 so i change the reading of the option in case that datatype is 4 ans subdatatype is 2.
I changed it to when num of options is less or equals than 3 i only read the 1st byte of each option as uint8 and not uint16.
My a6300 has only 3 Metering options so i cannot check how this works when a camera has more options, could you maybe check if you get the same problem?

I just try to figure some "Unknown" stuff out.
I got things in :Flash, ShootingMode, AutoFocusState, PictureEffect, RecordingVideo (value is Recording but it's off) so far

@pixeltris
Copy link
Owner

I think 0x80 values are just vendor specific values as noted in gphoto2. For standardized values 0x80 isn't used which is why some values have 0x80 and some don't.

https://github.com/gphoto/libgphoto2/blob/40dea37d256c093cea3b6044bd37ff49ae29945c/camlibs/ptp2/config.c#L4836

See the metering mode values used by this project / gphoto2

https://github.com/gphoto/libgphoto2/blob/40dea37d256c093cea3b6044bd37ff49ae29945c/camlibs/ptp2/config.c#L3662

public enum MeteringMode

@Nailik
Copy link
Author

Nailik commented May 31, 2020

Well jeah, your MeteringMode Ids do not work on my a6300.
What i tried to explain
Metering Mode Center :

  • when given as current it has value 0x0002
  • in the available values: 0x8002

@pixeltris
Copy link
Owner

pixeltris commented May 31, 2020

I'm not following what you're saying honestly. gphoto2 uses the same values as I do which are generically flagged as "SONY" (gphoto2 supports many sony cameras). So the values definitely should be correct.

EDIT: Oh I see what you're saying, the camera is stating a metering mode value which isn't even in the list of 'available values'. Not too sure what's going on there. I don't have my camera at the moment to test how it behaves on my machine.

It might be a bug in the firmware? Are any other values miss-matched? Is there any difference for 02 80 vs 02 00 when you send it back to the camera (i.e. does it report 02 80 when you send 02 80, or does it still say 02 00)? Maybe something sent 02 00 to the camera at some point and the camera just accepted it so it's now reporting that value?

@Nailik
Copy link
Author

Nailik commented May 31, 2020

Both is working, camera doesn't make a difference if i send 02 80 or 02 00 but i always receive: current 02 00 and available 02 80 - this destroys my idea how to handle the values (enums which are a little more complicated in dart)
👎

@pixeltris
Copy link
Owner

pixeltris commented May 31, 2020

That's weird, are there any other settings which have this behavior? You could possibly remap values which are reported incorrectly by checking if there's a mismatch between the available list and what's sent, then automatically append 0x8000 internally so that it at least maps up correctly on your side (assuming there's an equivilant matching 0x8000 e.g. 0x0002->0x8002).

@Nailik
Copy link
Author

Nailik commented May 31, 2020

Everything else - seems to work but i didn't test everything, currently it's more testing if it works well enough to make it a project.

Is there a way to contact you instead of commenting on this issue?
I think i would like to discuss something about this or may even give you my test project to test on your camera - if you have time.

@pixeltris
Copy link
Owner

pixeltris commented May 31, 2020

I don't currently have my camera around to test things, I might do in a month or so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants