diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2009-08-11 17:54:47 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2009-08-11 17:54:47 +0000 |
commit | ed73a3274ca4bb3dec0cf067732bcdf4fe1a7d62 (patch) | |
tree | 8ac2786b04bc7149ced718b8c80e98010b7164fc /firmware/usbstack | |
parent | 6cea3308d05c21aabe073f77c3d013485b0429a0 (diff) | |
download | rockbox-ed73a3274ca4bb3dec0cf067732bcdf4fe1a7d62.tar.gz rockbox-ed73a3274ca4bb3dec0cf067732bcdf4fe1a7d62.zip |
Add support for setting the clock using a special SCSI command. This is the same method that itunes uses, and there are host-side tools for it (e.g. libgpod)
Flyspray: FS#10514
Author: Laurent Papier and myself
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22255 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/usbstack')
-rw-r--r-- | firmware/usbstack/usb_storage.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index d29e731d5a..a6c960422d 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -31,6 +31,7 @@ | |||
31 | /* Needed to get at the audio buffer */ | 31 | /* Needed to get at the audio buffer */ |
32 | #include "audio.h" | 32 | #include "audio.h" |
33 | #include "usb_storage.h" | 33 | #include "usb_storage.h" |
34 | #include "timefuncs.h" | ||
34 | 35 | ||
35 | 36 | ||
36 | /* Enable the following define to export only the SD card slot. This | 37 | /* Enable the following define to export only the SD card slot. This |
@@ -68,8 +69,8 @@ | |||
68 | #define USB_BULK_RESET_REQUEST 0xff | 69 | #define USB_BULK_RESET_REQUEST 0xff |
69 | #define USB_BULK_GET_MAX_LUN 0xfe | 70 | #define USB_BULK_GET_MAX_LUN 0xfe |
70 | 71 | ||
71 | #define DIRECT_ACCESS_DEVICE 0x00 /* disks */ | 72 | #define DIRECT_ACCESS_DEVICE 0x00 /* disks */ |
72 | #define DEVICE_REMOVABLE 0x80 | 73 | #define DEVICE_REMOVABLE 0x80 |
73 | 74 | ||
74 | #define CBW_SIGNATURE 0x43425355 | 75 | #define CBW_SIGNATURE 0x43425355 |
75 | #define CSW_SIGNATURE 0x53425355 | 76 | #define CSW_SIGNATURE 0x53425355 |
@@ -86,6 +87,7 @@ | |||
86 | #define SCSI_WRITE_10 0x2a | 87 | #define SCSI_WRITE_10 0x2a |
87 | #define SCSI_START_STOP_UNIT 0x1b | 88 | #define SCSI_START_STOP_UNIT 0x1b |
88 | #define SCSI_REPORT_LUNS 0xa0 | 89 | #define SCSI_REPORT_LUNS 0xa0 |
90 | #define SCSI_WRITE_BUFFER 0x3b | ||
89 | 91 | ||
90 | #define UMS_STATUS_GOOD 0x00 | 92 | #define UMS_STATUS_GOOD 0x00 |
91 | #define UMS_STATUS_FAIL 0x01 | 93 | #define UMS_STATUS_FAIL 0x01 |
@@ -270,6 +272,7 @@ static void send_command_result(void *data,int size); | |||
270 | static void send_command_failed_result(void); | 272 | static void send_command_failed_result(void); |
271 | static void send_block_data(void *data,int size); | 273 | static void send_block_data(void *data,int size); |
272 | static void receive_block_data(void *data,int size); | 274 | static void receive_block_data(void *data,int size); |
275 | static void receive_time(void); | ||
273 | static void fill_inquiry(IF_MD_NONVOID(int lun)); | 276 | static void fill_inquiry(IF_MD_NONVOID(int lun)); |
274 | static void send_and_read_next(void); | 277 | static void send_and_read_next(void); |
275 | static bool ejected[NUM_DRIVES]; | 278 | static bool ejected[NUM_DRIVES]; |
@@ -288,6 +291,7 @@ static enum { | |||
288 | SENDING_RESULT, | 291 | SENDING_RESULT, |
289 | SENDING_FAILED_RESULT, | 292 | SENDING_FAILED_RESULT, |
290 | RECEIVING_BLOCKS, | 293 | RECEIVING_BLOCKS, |
294 | RECEIVING_TIME, | ||
291 | SENDING_CSW | 295 | SENDING_CSW |
292 | } state = WAITING_FOR_COMMAND; | 296 | } state = WAITING_FOR_COMMAND; |
293 | 297 | ||
@@ -459,6 +463,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length) | |||
459 | { | 463 | { |
460 | (void)ep; | 464 | (void)ep; |
461 | struct command_block_wrapper* cbw = (void*)cbw_buffer; | 465 | struct command_block_wrapper* cbw = (void*)cbw_buffer; |
466 | struct tm tm; | ||
462 | 467 | ||
463 | //logf("transfer result %X %d", status, length); | 468 | //logf("transfer result %X %d", status, length); |
464 | switch(state) { | 469 | switch(state) { |
@@ -602,6 +607,19 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length) | |||
602 | cur_sense_data.ascq=0; | 607 | cur_sense_data.ascq=0; |
603 | } | 608 | } |
604 | break; | 609 | break; |
610 | case RECEIVING_TIME: | ||
611 | tm.tm_year=(tb.transfer_buffer[0]<<8)+tb.transfer_buffer[1]; | ||
612 | tm.tm_yday=(tb.transfer_buffer[2]<<8)+tb.transfer_buffer[3]; | ||
613 | tb.transfer_buffer[8]; | ||
614 | tm.tm_hour=tb.transfer_buffer[5]; | ||
615 | tm.tm_min=tb.transfer_buffer[6]; | ||
616 | tm.tm_sec=tb.transfer_buffer[7]; | ||
617 | yearday_to_daymonth(tm.tm_yday,tm.tm_year,&tm.tm_mday,&tm.tm_mon); | ||
618 | tm.tm_wday=day_of_week(tm.tm_mon,tm.tm_mday,tm.tm_year); | ||
619 | tm.tm_year -= 1900; | ||
620 | set_time(&tm); | ||
621 | send_csw(UMS_STATUS_GOOD); | ||
622 | break; | ||
605 | } | 623 | } |
606 | } | 624 | } |
607 | 625 | ||
@@ -1063,6 +1081,21 @@ static void handle_scsi(struct command_block_wrapper* cbw) | |||
1063 | } | 1081 | } |
1064 | break; | 1082 | break; |
1065 | 1083 | ||
1084 | case SCSI_WRITE_BUFFER: | ||
1085 | if(cbw->command_block[1]==1 | ||
1086 | && cbw->command_block[2]==0 | ||
1087 | && cbw->command_block[3]==0x0c | ||
1088 | && cbw->command_block[4]==0 | ||
1089 | && cbw->command_block[5]==0 | ||
1090 | && cbw->command_block[6]==0 | ||
1091 | && cbw->command_block[7]==0 | ||
1092 | /* Some versions of itunes set the next byte to 0. Technically | ||
1093 | * it should be 0x0c */ | ||
1094 | && (cbw->command_block[8]==0 || cbw->command_block[8]==0x0c) | ||
1095 | && cbw->command_block[9]==0) | ||
1096 | receive_time(); | ||
1097 | break; | ||
1098 | |||
1066 | default: | 1099 | default: |
1067 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); | 1100 | logf("scsi unknown cmd %x",cbw->command_block[0x0]); |
1068 | send_csw(UMS_STATUS_FAIL); | 1101 | send_csw(UMS_STATUS_FAIL); |
@@ -1091,6 +1124,11 @@ static void send_command_failed_result(void) | |||
1091 | state = SENDING_FAILED_RESULT; | 1124 | state = SENDING_FAILED_RESULT; |
1092 | } | 1125 | } |
1093 | 1126 | ||
1127 | static void receive_time(void) | ||
1128 | { | ||
1129 | usb_drv_recv(ep_out, tb.transfer_buffer, 12); | ||
1130 | state = RECEIVING_TIME; | ||
1131 | } | ||
1094 | static void receive_block_data(void *data,int size) | 1132 | static void receive_block_data(void *data,int size) |
1095 | { | 1133 | { |
1096 | usb_drv_recv(ep_out, data, size); | 1134 | usb_drv_recv(ep_out, data, size); |